package com.zbkj.crmeb.merchant.api.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.constants.WeChatConstants;
import com.taobao.pac.sdk.cp.dataobject.response.CAINIAO_GLOBAL_GPS_XPO.order;
import com.utils.*;
import com.utils.lianlianpay.client.LLianPayClient;
import com.utils.monitor.DingMsgEnum;
import com.utils.monitor.DingTalkMsgUtil;
import com.utils.query.QueryCityItem;
import com.zbkj.crmeb.chant.service.IChannelMerchantAccountService;
import com.zbkj.crmeb.chant.service.MerchantAddressService;
import com.zbkj.crmeb.enums.*;
import com.zbkj.crmeb.front.request.*;
import com.zbkj.crmeb.front.response.*;
import com.zbkj.crmeb.front.vo.CityItemVo;
import com.zbkj.crmeb.front.vo.ProvinceCityItemVo;
import com.zbkj.crmeb.store.model.*;
import com.zbkj.crmeb.store.service.*;
import com.zbkj.crmeb.user.dao.UserAddressDao;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.crmeb.core.utils.RedisUtil;
import com.factory.CommonFactory;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zbkj.crmeb.chant.model.ChannelActivity;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.chant.service.ChannelActivityService;
import com.zbkj.crmeb.chant.service.IChannelMerchantService;
import com.zbkj.crmeb.express.model.Express;
import com.zbkj.crmeb.express.service.ExpressService;
import com.zbkj.crmeb.express.service.LogisticService;
import com.zbkj.crmeb.express.service.ShippingTemplatesService;
import com.zbkj.crmeb.express.vo.LogisticsResultVo;
import com.zbkj.crmeb.front.vo.OrangeWechatAppletConfigVo;
import com.zbkj.crmeb.front.vo.OrderAgainVo;
import com.zbkj.crmeb.marketing.model.StoreCouponUser;
import com.zbkj.crmeb.marketing.response.StoreCouponUserResponse;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.member.model.MemberPointsManagement;
import com.zbkj.crmeb.member.service.IMemberPointsManagementService;
import com.zbkj.crmeb.merchant.api.request.UpdatePickingProductRequest;
import com.zbkj.crmeb.merchant.api.response.EnableIntegralResponse;
import com.zbkj.crmeb.merchant.api.service.MerOrderService;
import com.zbkj.crmeb.merchant.api.service.MerStoreCartService;
import com.zbkj.crmeb.order.AbstractStoreOrderService;
import com.zbkj.crmeb.order.StoreOrderFactory;
import com.zbkj.crmeb.order.oprocess.IOrderProcess;
import com.zbkj.crmeb.order.pprocess.AdapayDegreePayOrderProcess;
import com.zbkj.crmeb.payment.service.OrderPayService;
import com.zbkj.crmeb.payment.vo.wechat.CreateOrderResponseVo;
import com.zbkj.crmeb.payment.wechat.WeChatPayService;
import com.zbkj.crmeb.store.request.DeliveryRequest;
import com.zbkj.crmeb.store.request.OrderInfoDeliveryRequest;
import com.zbkj.crmeb.store.request.StoreOrderInfoSearchRequest;
import com.zbkj.crmeb.store.request.StoreOrderSendRequest;
import com.zbkj.crmeb.store.request.StoreProductReplyAddRequest;
import com.zbkj.crmeb.store.response.DeliveryResponse;
import com.zbkj.crmeb.store.response.StoreCartResponse;
import com.zbkj.crmeb.store.utilService.OrderUtils;
import com.zbkj.crmeb.store.vo.StoreOrderInfoVo;
import com.zbkj.crmeb.system.model.SystemAttachment;
import com.zbkj.crmeb.system.model.SystemStore;
import com.zbkj.crmeb.system.service.*;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserAddress;
import com.zbkj.crmeb.user.model.UserMemberRecord;
import com.zbkj.crmeb.user.service.UserAddressService;
import com.zbkj.crmeb.user.service.UserMemberRecordService;
import com.zbkj.crmeb.user.service.UserService;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;

/**
 * @Classname StoreOrderServiceImpl
 * @Description H5端订单操作
 * @Date 2020/7/4 11:26 上午
 * @Created by stivepeim
 */
@Slf4j
@Service
public class MerOrderServiceImpl implements MerOrderService {
    @Autowired
    private UserService userService;
    @Autowired
    private MerStoreCartService storeCartService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    @Autowired
    private StoreOrderStatusService storeOrderStatusService;
    @Autowired
    private ShippingTemplatesService shippingTemplatesService;
    @Autowired
    private UserAddressService userAddressService;
    @Autowired
    SystemAdminService systemAdminService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private StoreProductReplyService storeProductReplyService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SystemStoreService systemStoreService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private SystemAttachmentService systemAttachmentService;
    @Autowired
    private LogisticService logisticsService;
    @Autowired
    StoreOrderTaskService storeOrderTaskService;
    @Autowired
    WeChatPayService weChatPayService;
    @Autowired
    private ProductUtil productUtil;
    @Autowired
    private PriceUtil priceUtil;
    @Autowired
    private CommonFactory commonFactory;
    @Autowired
    private MessageConfigService messageConfigService;
    @Autowired
    private IChannelMerchantService channelMerchantService;
    @Autowired
    StoreCouponUserService storeCouponUserService;
    @Autowired
    private StoreOrderInfoPickingService storeOrderInfoPickingService;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private ChannelActivityService channelActivityService;
    @Autowired
    private StoreProductActivityService storeProductActivityService;
    @Autowired
    private UserMemberRecordService userMemberRecordService;
    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    private StoreOrderRefundApplyService storeOrderRefundApplyService;
    @Autowired
    private IChannelMerchantAccountService channelMerchantAccountService;
    @Autowired
    private ExpressService expressService;
    @Autowired
    private StoreSaleAnalysisService storeSaleAnalysisService;
    @Autowired
    private AdapayDegreePayOrderProcess adapayDegreePayOrderProcess;
    @Autowired
    private StoreOrderTransService storeOrderTransService;
    @Autowired
    private SupplierService supplierService;
    @Autowired
    StoreOrderFactory storeOrderFactory;
    @Autowired
    private OrderInfoDeliveryService orderInfoDeliveryService;
    @Autowired
    private StoreProductService storeProductService;
    @Autowired
    private IMemberPointsManagementService memberPointsManagementService;
    @Autowired
    private Redisson redisson;
    @Autowired
    private StoreOrderGroupInfoService storeOrderGroupInfoService;
    @Autowired
    private UserAddressDao userAddressDao;

    @Resource
    private KeyValueService keyValueService;

    @Value("${orange.payCatalog}")
    private String payCatalog;
    @Value("${orange.wxAppId}")
    private String wxAppId;
    @Value("${orange.evn}")
    private String evn;
    @Value("${orange.originalld}")
    private String originalld;
    @Value("${order.yueMerIds}")
    private List<Integer> yueMerIds;
	@Value("${order.push.jky}")
	private boolean jkyPush;

    /**
     * 确认订单
     *
     * @param cartIds 购物车id集合
     * @param isNew   是否再次下单=从缓存中获取数据
     * @return 确认订单response
     */
    @Override
    public ConfirmOrderResponse confirmOrder(List<Integer> cartIds, boolean isNew, Integer merId, Integer skuId, Integer discountPackageId, String groupId) {
        ConfirmOrderResponse response = new ConfirmOrderResponse();
        response.setIsStock(true);
        // 获取运费默认模版 , 应该跟着商品走
//        ShippingTemplates template = shippingTemplatesService.getById(1);// todo 这里的默认模版写死
//        if (null == template) {
//            throw new CrmebException("默认模板未配置，无法下单");
//        }
        User currentUserInfo = userService.getInfo();
        ChannelMerchant channelMerchant = channelMerchantService.getById(merId);
        List<StoreCartResponse> storeCartResponse = new ArrayList<>();
        // isNew=false 从购物车获取 isNew=true 从缓存中获取=再次下单
        if (isNew) {
            storeCartResponse = orderUtils.getCacheOrderAgain(cartIds.get(0) + ""); // todo 按照存储规格这里应该只会有一个值

        } else {
            // TODO DIDIOK PRICE -2
            storeCartResponse = storeCartService.getListByUserIdAndCartIds(currentUserInfo.getUid(), cartIds, channelMerchant, groupId);
        }

        try {
            List<Integer> productIdList = storeCartResponse.stream().map(StoreCartResponse::getProductId).collect(Collectors.toList());
            // 校验是否支持自提
            boolean isAllowSelfPickUp = orderUtils.checkAllowSelfPickUpList(merId, productIdList, groupId);
            if(isAllowSelfPickUp){
                response.setIsAllowSelfPickUp(SwitchEnum.OPEN.getCode());
            }
        }catch (Exception e){
            log.error("校验是否支持自提异常，", e);
        }
        //商品是否为拼团商品
        if (Objects.nonNull(skuId) && cartIds.size() == 1){
            // TODO DIDIOK PRICE -9
            storeOrderGroupInfoService.dealGroupActivityProduct(currentUserInfo, storeCartResponse, channelMerchant, skuId, groupId);
        } else {
            dealActivityProduct(currentUserInfo, storeCartResponse, channelMerchant);
        }

        Integer stock = 0;
        for (StoreCartResponse cart : storeCartResponse) {
            if (ProductTypeEnum.BUYER == ProductTypeEnum.valueOf(cart.getProductInfo().getIsEurope()) || ProductTypeEnum.EUROPE == ProductTypeEnum.valueOf(cart.getProductInfo().getIsEurope()) || ProductTypeEnum.IM == ProductTypeEnum.valueOf(cart.getProductInfo().getIsEurope())) {
//            if (ProductTypeEnum.BUYER == ProductTypeEnum.valueOf(cart.getProductInfo().getIsEurope()) || ProductTypeEnum.EUROPE == ProductTypeEnum.valueOf(cart.getProductInfo().getIsEurope()) || ProductTypeEnum.XYY == ProductTypeEnum.valueOf(cart.getProductInfo().getIsEurope())) {
                String barCode = cart.getProductInfo().getBarCode();
                if (barCode.startsWith(BarCodeEnum.BUYER.getCode().toString())) {
                    stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(), cart.getProductInfo().getAttrInfo().getSourceSkuId(), null, cart.getCartNum());
                } else if (barCode.startsWith(BarCodeEnum.EUROPE.getCode().toString())) {
                    String[] sukArr = cart.getProductInfo().getAttrInfo().getSuk().split(",");
                    if (cart.getProductInfo().getAttrInfo().getSuk().contains(",")) {
                        stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(), "", sukArr[1], cart.getCartNum());
                    } else {
                        stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(), "", sukArr[0], cart.getCartNum());
                    }
                } else if (barCode.startsWith(BarCodeEnum.IM.getCode().toString())) {
                    //in
                    stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(), cart.getProductInfo().getAttrInfo().getSourceSkuId(), null, cart.getCartNum());
                }
//                else if (barCode.startsWith(BarCodeEnum.XYY.getCode().toString())) {
//                    stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(), cart.getProductInfo().getAttrInfo().getSourceSkuId(), null, cart.getCartNum());
//                }
//                else if(barCode.startsWith(BarCodeEnum.LEAM.getCode().toString())){
//                    stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(),cart.getProductInfo().getAttrInfo().getSourceSkuId(), null, cart.getCartNum());
//                }
                else if (barCode.startsWith(BarCodeEnum.GB.getCode().toString())) {
                    stock = productUtil.getStockByBarCode(cart.getProductInfo().getBarCode(), cart.getProductInfo().getAttrInfo().getSourceSkuId(), null, cart.getCartNum());
                }
                log.info("查询下单商品库存返回结果,商品名称:{},库存stock:{}", cart.getProductInfo().getStoreName(), stock);
                if (stock < 1) {
                    response.setIsStock(false);
                    return response;
                }
                cart.setTrueStock(stock);
            }
        }

        // todo 跳过拼团秒杀和砍价

        // todo 后面这里需要根据参数判定，不能一直使用默认收货地址
        UserAddress defaultAddress = userAddressService.getDefault();
        //        if(null == defaultAddress) throw new CrmebException("未配置默认收货地址");

        // 计算订单金额
        // TODO DIDIOK PRICE -4
        PriceGroupResponse orderPriceGroup = priceUtil.getOrderPriceGroup(storeCartResponse, defaultAddress, merId);
        //商户积分配置
        HashMap<String, Object> otherMap = new HashMap<>();
        if (orderPriceGroup.getPickingId() == 0) {
            if (channelMerchant != null && channelMerchant.getAppletType() == 1 && orderPriceGroup.getTaxAndSecondPrice() != null) {
                orderPriceGroup.setPayPrice(orderPriceGroup.getPayPrice().add(orderPriceGroup.getTaxAndSecondPrice()));
                orderPriceGroup.setTaxAndSecondPrice(new BigDecimal(0));
            }
            MemberPointsManagement management = Optional.ofNullable(memberPointsManagementService.getOne(Wrappers.<MemberPointsManagement>lambdaQuery().eq(MemberPointsManagement::getMerId, merId).last("LIMIT 1"))).orElse(new MemberPointsManagement());
            otherMap.put(Constants.CONFIG_KEY_INTEGRAL_ENABLE, management.getPointsEnableFlag());
            otherMap.put(Constants.CONFIG_KEY_INTEGRAL_RATE, management.getPointsRatio());
            otherMap.put(Constants.CONFIG_KEY_INTEGRAL_RATE_ORDER_GIVE, management.getOrderOintsProportion());
            otherMap.put(Constants.CONFIG_KEY_INTEGRAL_PRICE_DEDUCTION_RATIO, management.getPriceUsageRatio());
            // 获取有效优惠券,过滤活动商品
            List<StoreCartResponse> collect = storeCartResponse.stream().filter(storeCartResponse1 -> Objects.isNull(storeCartResponse1.getChannelActivity())).filter(e -> Objects.isNull(e.getActivityGroupId())).collect(Collectors.toList());
            List<StoreCouponUserResponse> canUseUseCouponList = orderUtils.getCanUseCouponList(collect, false, orderPriceGroup, defaultAddress, channelMerchant);
            //List<StoreCouponUserResponse> canUseUseCouponList = orderUtils.getCanUseCouponList(storeCartResponse, false, orderPriceGroup, defaultAddress, channelMerchant);
            // 设置response信息
            StoreCouponUserResponse canUserCoupon = null;
            if (null != canUseUseCouponList && canUseUseCouponList.size() > 0) {
                canUserCoupon = canUseUseCouponList.get(0);
            }
            response.setUsableCoupon(canUserCoupon);
        }
        //判断默认地址是否符合批采收货类型
        response.setAddressInfo(defaultAddress);
        // 默认地址为空使用自提地址
        if (null == defaultAddress){
            response.setAddressInfo(new UserAddress());
        }
        if (defaultAddress != null && orderPriceGroup.getPickingId() > 0 && !Objects.equals(defaultAddress.getAreaType(), orderPriceGroup.getAreaType())) {
            response.setAddressInfo(null);
        }
        response.setDiscountPackageId(discountPackageId);
        response.setCartInfo(storeCartResponse);
        // TODO DIDIOK PRICE -3
        response.setPriceGroup(orderPriceGroup);
        response.setUserInfo(currentUserInfo);
        response.setOfflinePayStatus(systemConfigService.getValueByKey("offline_pay_status"));
        response.setYuePayStatus((systemConfigService.getValueByKey("balance_func_status").equals("1") && systemConfigService.getValueByKey("yue_pay_status").equals("1")) ? "1" : "2"); // 1开启 2关闭
        response.setPayWeixinOpen(systemConfigService.getValueByKey("pay_weixin_open"));
        response.setStoreSelfMention(systemConfigService.getValueByKey("store_self_mention"));
        response.setOther(otherMap);
        response.setSystemStore(null);
        response.setOrderKey(orderUtils.cacheSetOrderInfo(currentUserInfo.getUid(), response));
        log.info("确认订单 response：{}", JSONObject.toJSONString(response));
        return response;
    }

    private void dealActivityProduct(User currentUserInfo, List<StoreCartResponse> storeCartResponse, ChannelMerchant channelMerchant) {
        if (storeCartResponse.get(0).getPickingId() == 0) {
            //返回用户类型
            List<Integer> list = getUserType(currentUserInfo);
            Map<Integer, Integer> map = new HashMap<>();
            //根据商品id分组
            Map<Integer, List<StoreCartResponse>> cartMap = storeCartResponse.stream().collect(Collectors.groupingBy(StoreCartResponse::getProductId));
            for (Map.Entry<Integer, List<StoreCartResponse>> entry : cartMap.entrySet()) {
                Integer productId = entry.getKey();
                ChannelActivity activity = channelActivityService.getOne(Wrappers.<ChannelActivity>lambdaQuery()
                        .eq(ChannelActivity::getIsDel, 0)
                        .eq(ChannelActivity::getMerId, channelMerchant.getId())
                        .gt(ChannelActivity::getEndTime, new Date())
                        .inSql(ChannelActivity::getId, "SELECT activity_id from eb_store_product_activity where product_id = " + productId)
                        .orderByAsc(ChannelActivity::getStartTime)
                        .last("LIMIT 1")
                );
                if (activity == null) {
                    continue;
                }
                List<StoreCartResponse> entryValue = entry.getValue();
                //判断购买价格
                if (currentUserInfo.getCreateTime().getTime() > activity.getCreateTime().getTime()) {
                    list.add(3);
                }
                if (list.contains(activity.getCrowd())) {
                    //未开始判断是否能够购买(0不可购买  1按照售价购买 2秒杀价购买 )
                    if (activity.getStartTime().after(new Date())) {
                        if (activity.getPreheating() != 3 && activity.getPreheatingStartTime().before(new Date()) && activity.getPreheatingEndTime().after(new Date())) {
                            //预售不可购买
                            if (activity.getPreheatingBuy() == 0) {
                                throw new CrmebException(activity.getName() + "活动预售不可购买!");
                            }
                        }
                    } else {
                        List<String> sourceSkuIdList = entryValue.stream().map(e -> e.getProductInfo().getAttrInfo().getSourceSkuId()).distinct().collect(Collectors.toList());
                        //计算商品秒杀价
                        List<StoreProductActivity> productActivityList = storeProductActivityService.list(Wrappers.<StoreProductActivity>lambdaQuery()
                                .eq(StoreProductActivity::getActivityId, activity.getId())
                                .eq(StoreProductActivity::getProductId, productId)
                                .in(StoreProductActivity::getSourceSkuId, sourceSkuIdList)
                                .gt(StoreProductActivity::getSpikePrice, 0)
                        );
                        Map<String, BigDecimal> activityMap = productActivityList.stream().collect(Collectors.toMap(StoreProductActivity::getSourceSkuId, StoreProductActivity::getSpikePrice));
                        //活动开始不限量
                        if (activity.getLimitTotal() == 0) {
                            setSpikePrice(channelMerchant, entryValue, activityMap, activity);
                        } else {
                            //限量处理
                            int count = storeOrderInfoService.count(Wrappers.<StoreOrderInfo>lambdaQuery()
                                    .eq(StoreOrderInfo::getActivityId, activity.getId())
                                    .gt(StoreOrderInfo::getCreateTime, activity.getStartTime())
                                    .inSql(StoreOrderInfo::getOrderId, "SELECT id FROM eb_store_order where mer_id = " + channelMerchant.getId() + " and uid = " + currentUserInfo.getUid())
                            );
                            //限购处理
                            int sum = entryValue.stream().mapToInt(StoreCartResponse::getCartNum).sum();
                            map.put(activity.getId(), map.containsKey(activity.getId()) ? map.get(activity.getId()) + sum : sum);
                            if (activity.getLimited() == 0) {
                                //超出限购  无法购买
                                if (activity.getLimitTotal() <= count) {
                                    if (activity.getLimited() == 0) {
                                        throw new CrmebException(StrUtil.format("{}活动期间已购买{}件,限购{}件", activity.getName(), count, activity.getLimitTotal()));
                                    }
                                } else {
                                    int i = activity.getLimitTotal() - count;
                                    if (map.get(activity.getId()) > i) {
                                        throw new CrmebException(StrUtil.format("{}活动期间已购买{}件,限购{}件,还能购买{}件", activity.getName(), count, activity.getLimitTotal(), i));
                                    } else {
                                        setSpikePrice(channelMerchant, entryValue, activityMap, activity);
                                    }
                                }
                            } else {
                                if (activity.getLimitTotal() > count) {
                                    int i = activity.getLimitTotal() - count;
                                    if (map.get(activity.getId()) > i) {
                                        throw new CrmebException(StrUtil.format("{}活动期间已购买{}件,限购{}件,还能以秒杀价购买{}件", activity.getName(), count, activity.getLimitTotal(), i));
                                    } else {
                                        setSpikePrice(channelMerchant, entryValue, activityMap, activity);
                                    }
                                }
                            }
                        }
                    }
                }
                list.remove(new Integer(3));
            }
        }
    }

    private List<Integer> getUserType(User currentUserInfo) {
        List<Integer> list = new ArrayList<>();
        if (currentUserInfo != null) {
            list.add(1);
            // 无订单用户
            int orderCount = storeOrderService.
                    count(Wrappers.<StoreOrder>lambdaQuery().eq(StoreOrder::getUid, currentUserInfo.getUid()));
            if (0 == orderCount) {
                list.add(2);
            }
            //查询用户是否已开启会员
            int count = userMemberRecordService.count(Wrappers.lambdaQuery(UserMemberRecord.class)
                    .eq(UserMemberRecord::getPaid, true)
                    .gt(UserMemberRecord::getExpirationTime, new Date())
                    .eq(UserMemberRecord::getUid, currentUserInfo.getUid()));
            if (count > 0) {
                list.add(4);
            }
        }
        return list;
    }

    private void setSpikePrice(ChannelMerchant channelMerchant, List<StoreCartResponse> entryValue, Map<String, BigDecimal> activityMap, ChannelActivity activity) {
        for (StoreCartResponse cartResponse : entryValue) {
            cartResponse.setChannelActivity(activity);
            BigDecimal spikePrice = activityMap.get(cartResponse.getProductInfo().getAttrInfo().getSourceSkuId());
            if (spikePrice != null) {
                cartResponse.setTruePrice(spikePrice);
                if (channelMerchant.getAppletType() == 1) {
                    cartResponse.setTruePrice(cartResponse.getTruePrice().subtract(cartResponse.getTaxAndSecondPrice()));
                }
            }
        }
    }

    /**
     * 订单创建
     *
     * @param request  创建订单参数
     * @param orderKey orderKey
     * @return 创建订单结果
     */
    @Override
    public OrderPayResponse createOrder(OrderCreateRequest request, String orderKey, String ip) {
        ChannelMerchant channelMerchant = channelMerchantService.getById(request.getMerId());
        if (request.getShippingType() == 2 && channelMerchant.getIsTake() == 0) {
            throw new CrmebException("该商户自提商品功能已关闭");
        }
        if (-1 != yueMerIds.indexOf(request.getMerId()) && Constants.PAY_TYPE_YUE.equals(request.getPayType())) {
            throw new CrmebException("该商户余额支付功能已关闭");
        }

        // 获取支付渠道
        Integer type = orderUtils.getOrderPayType(request.getMerId()).getCode();
        IOrderProcess orderProcess = commonFactory.getOrderType(type);
        // TODO DIDIOK 支付0
        OrderPayResponse orderPayResponse = orderProcess.creatOrder(orderKey, request, ip);
        final String idCard = request.getIdCard();
        final String idName = request.getIdName();
        final String seatNo = request.getSeatNo();
        final Integer addressId = request.getAddressId();
        ExecutorService thread = ThreadPoolUtils.getThread();
        thread.execute(()->{
            try {
                LambdaQueryWrapper<UserAddress> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(UserAddress::getId, addressId);
                UserAddress userAddress = userAddressDao.selectOne(lambdaQueryWrapper);
                String srcIdCard = userAddress.getIdCard();
                String srcIdName = userAddress.getIdName();
                String srcSeatNo = userAddress.getSeatNo();
                if (StringUtils.isAnyBlank(srcIdCard,srcIdName) && !StringUtils.isAnyBlank(idCard,idName)){
                    userAddress.setIdCard(idCard);
                    userAddress.setIdName(idName);
                }
                if (StringUtils.isBlank(srcSeatNo) && StringUtils.isNotBlank(seatNo)) {
                    userAddress.setSeatNo(seatNo);
                }
                userAddressDao.updateById(userAddress);
            }catch (Exception e){
                log.error("建单保存用户支付信息失败:",e);
            }
            DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,"创建订单,入参 "+JSON.toJSONString(request)+";"+ip+";"+orderKey+";响应："+JSONObject.toJSONString(orderPayResponse));
        });


        return orderPayResponse;
    }
    /**
     * 再次支付
     * @author daigb
     * @date:  2022-07-18 16:01
     */
    public OrderPayResponse getPayToken(String orderId, Integer merId, String ip) {
        log.info("连连再次支付 getPayToken：{},{},{}", orderId, merId, ip);
        StoreOrder order = storeOrderService.getByOrderId(orderId);
        // 创建订单数据
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        orderPayResponse.setStatus(Constants.LIANLIAN_DEGREE_PAY);
        orderPayResponse.addExtend("orderId",orderId);

        // 基础参数
        LianlianPayRequest payRequest = getPayParams(order, merId, ip);
        log.info("--------------- 连连再次支付原数据: {}", JSON.toJSONString(payRequest));
        LLianPayClient lLianPayClient = new LLianPayClient();
        String payResult = lLianPayClient.sendRequest(Constants.PAY_URL_PROD, JSON.toJSONString(payRequest));
        log.info("--------------- 连连再次支付返回结果数据: {}", JSON.toJSONString(payResult));

        // 下单结果
        LianlianPayResponse response = JSONObject.parseObject(payResult, LianlianPayResponse.class);

        String ret_code = response.getRet_code();
        String ret_msg = response.getRet_msg();
        String payload = response.getPayload();


        // 返回结果
        Map<String, Object> result = new HashMap<>();
        if ("0000".equals(ret_code)) {
            log.info("--------------- 连连再次支付成功! payload: {}", JSON.toJSONString(payload));
            JSONObject jsonObject = JSONObject.parseObject(payload);
            if(null != jsonObject) {
                if(null != jsonObject.get("appid")) {
                    result.put("appid", jsonObject.get("appid").toString());
                }
                if(null != jsonObject.get("token")) {
                    result.put("token", jsonObject.get("token").toString());
                }
            }
            result.put("result", "SUCCESS");
        } else {
            result.put("result", ret_msg);
            log.error("--------------- 连连再次支付失败!: {}", JSON.toJSONString(payResult));
        }

        orderPayResponse.setResult(result);
        return orderPayResponse;
    }

    /**
     * 基础参数组装
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private LianlianPayRequest getPayParams(StoreOrder order, Integer merId, String ip) {
        log.info("连连支付网关类支付 getPayParams：{},{},{}", JSONObject.toJSONString(order), merId, ip);
        LianlianPayRequest payRequest = new LianlianPayRequest();

        String timestamp = LLianPayDateUtils.getTimestamp();
        Integer user_id = order.getUid();
        User user = null;
        String userCreateTime = null;
        String userTel = null;
        if(user_id != null) {
            user = userService.getById(order.getUid());
            if(user != null) {
                userCreateTime = DateUtil.dateToStr(user.getCreateTime(), Constants.DATE_TIME_FORMAT_NUM);
                userTel = user.getPhone();
            }
        }

        List<StoreOrderInfoVo> orderInfoList = storeOrderInfoService.getOrderListByOrderId(order.getId());
        if(orderInfoList.size() < 1){
            throw new CrmebException("在订单里没有找到商品数据");
        }
        String goods_name = orderInfoList.get(0).getInfo().getProductInfo().getStoreName();
        Integer goods_count = orderInfoList.stream().mapToInt(e -> e.getNum() == null ? 0 : e.getNum()).sum();

        payRequest.setTimestamp(timestamp);
        payRequest.setOid_partner(Constants.OID_PARTNER_PROD_TUGOU);
        // 业务扩展字段。渠道扩展字段JSON串 payName和idCard
        LianlianPayExtendParamsRequest extendParamsRequest = new LianlianPayExtendParamsRequest();
        LianlianPayExtendParamsRequest.ExtendParamsIdentityRequest identityRequest= new LianlianPayExtendParamsRequest.ExtendParamsIdentityRequest();
        identityRequest.setType("IDCARD");
        identityRequest.setName(order.getPayName());
        identityRequest.setNumber(order.getIdCard());
        extendParamsRequest.setIdentity(identityRequest);
        String extendParams = JSONObject.toJSONString(extendParamsRequest);
        payRequest.setExtend_params(extendParams);

        payRequest.setTxn_seqno(order.getOrderId());
        payRequest.setTotal_amount(order.getPayPrice());

        RiskItemRequest riskItemRequest = new RiskItemRequest();
        // 基础类风控参数，原来是4008，连连要求修改
        riskItemRequest.setFrms_ware_category("4016");
        riskItemRequest.setUser_info_mercht_userno(user_id == null ? null : String.valueOf(user_id));
        // TODO 用户绑定手机号
        if(userTel == null){
            userTel = order.getUserPhone();
        }
        if (StringUtils.isNotEmpty(userTel) && userTel.startsWith("0|+86")) {
            userTel = userTel.substring(5).trim();
        }else if (StringUtils.isNotEmpty(userTel) && userTel.startsWith("+86")){
            userTel = userTel.substring(3).trim();
        }
        riskItemRequest.setUser_info_bind_phone(userTel);

        riskItemRequest.setUser_info_dt_register(userCreateTime);
        riskItemRequest.setGoods_name(goods_name);
        // 实物类风控参数
        riskItemRequest.setVirtual_goods_status("0");
        riskItemRequest.setGoods_count(String.valueOf(goods_count));
        riskItemRequest.setDelivery_full_name(order.getRealName());
        String deliveryPhone = order.getUserPhone();
        if (StringUtils.isNotEmpty(deliveryPhone) && deliveryPhone.startsWith("0|+86")) {
            deliveryPhone = deliveryPhone.substring(5).trim();
        }else if (StringUtils.isNotEmpty(deliveryPhone) && deliveryPhone.startsWith("+86")){
            deliveryPhone = deliveryPhone.substring(3).trim();
        }
        riskItemRequest.setDelivery_phone(deliveryPhone);
        // 物流方式:普通快递。
        riskItemRequest.setLogistics_mode("2");
        // TODO 发货时间: other - 72小时以后。
        riskItemRequest.setDelivery_cycle("other");

        String provinceCode = queryProvinceCityCode(order.getProvince(), true);
        String cityCode = queryProvinceCityCode(order.getCity(), false);
        riskItemRequest.setDelivery_addr_province(provinceCode);
        riskItemRequest.setDelivery_addr_city(cityCode);
        payRequest.setRisk_item(JSONObject.toJSONString(riskItemRequest));

        // 终端用户IP。支持IPV4和IPV6两种格式的IP地址。
        payRequest.setClient_ip(ip);

        // 付款方信息payerInfo
        PayerInfoRequest payerInfoRequest = new PayerInfoRequest();
        payerInfoRequest.setPayer_type("USER");
        payerInfoRequest.setPayer_id(order.getUid() == null ? null : String.valueOf(order.getUid()));

        payRequest.setPayerInfo(payerInfoRequest);

        // 付款方式信息payMethods
        List<PayMethodsRequest> payMethodsRequestList = new ArrayList<>();

        PayMethodsRequest payMethodsRequest = new PayMethodsRequest();
        payMethodsRequest.setMethod("WECHAT_APP_WXA");
        payMethodsRequest.setAmount(order.getPayPrice());

        payMethodsRequestList.add(payMethodsRequest);
        payRequest.setPayMethods(payMethodsRequestList);

        return payRequest;
    }

    /**
     * 获取省市编码
     *
     * @param
     */
    private String queryProvinceCityCode(String address, boolean isProvince) {

        if(StringUtils.isEmpty(address)){
            return null;
        }
        JSONArray jsonArray = null;
        try {
            // json列表查询的
            jsonArray = QueryCityItem.getMethodConfig();
        } catch (Exception e) {
            log.error("获取省市编码异常:{}", e.fillInStackTrace());
            throw new CrmebException("获取省市编码异常");
        }

        List<ProvinceCityItemVo> itemDtoList = JSON.parseArray(jsonArray.toString(), ProvinceCityItemVo.class);

        for(ProvinceCityItemVo provinceCityItemVo : itemDtoList){
            if(isProvince) {
                if (provinceCityItemVo.getRegion() != null && provinceCityItemVo.getRegion().contains(address)) {
                    return provinceCityItemVo.getCode();
                }
            }else {
                List<CityItemVo> cityItemVoList = provinceCityItemVo.getRegionEntitys();
                if (org.apache.commons.collections.CollectionUtils.isEmpty(cityItemVoList)) {
                    continue;
                }
                for (CityItemVo cityItemVo : cityItemVoList) {
                    if (cityItemVo.getRegion() != null && cityItemVo.getRegion().contains(address)) {
                        return cityItemVo.getCode();
                    }
                }
            }
        }
        return null;
    }

    /**
     * 用户订单分账
     * @author daigb
     * @date:  2022-09-22 11:10
     */
    @Override
    @Async("taskExecutor")
    public void transDivByOrder(StoreOrder storeOrder, List<StoreOrderInfo> storeOrderInfoList) {
    	try {
			// TODO 目前只有8F品牌店会进行汇付支付和分账, 汇付方修改周期2个月
			if(18 != storeOrder.getMerId()) {
				return;
			}

			log.info("--------------- 订单{}开始进入分账业务 ---------------", storeOrder.getOrderId());
			// 只有汇付聚合支付并且是云仓商品会使用分账业务
			if(!PayTypeEnum.ADAPAY_DEGREE.getMsg().equals(storeOrder.getPayType())) {
				log.info("--------------- 该订单{}不属于分账类型 ---------------", storeOrder.getOrderId());
				return;
			}
			
			// 循环所有子订单, 计算分账金额
			boolean isTransDiv = false;
			BigDecimal totalCostPrice = BigDecimal.ZERO; // 平台成本价
			BigDecimal totalTaxPrice = BigDecimal.ZERO; // 运税费
			List<Integer> infoIds = new ArrayList<>(); // 分账子订单记录
			for(StoreOrderInfo orderInfo : storeOrderInfoList) {
				// 只有云仓进行分账
				if(null != orderInfo.getIsEurope() && ProductTypeEnum.INSIDE != ProductTypeEnum.valueOf(orderInfo.getIsEurope())) {
					infoIds.add(orderInfo.getId());
					
			        StoreCartResponse storeCartResponse = JSON.parseObject(orderInfo.getInfo(), StoreCartResponse.class);
			        StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
			        totalCostPrice = totalCostPrice.add(attrInfo.getCost());
			        totalTaxPrice = totalTaxPrice.add(attrInfo.getTaxAndSecondPrice());
			        isTransDiv = true;
				}
			}
			// 无需分账
			if(!isTransDiv) {
				log.info("--------------- 该订单{}无需分账 ---------------", storeOrder.getOrderId());
				return;
			}
			// 实际分账业务
			BigDecimal totalPrice = totalCostPrice.add(totalTaxPrice);
			// 计算去除手续费后实际可分金额
			BigDecimal hfServicePrice = storeOrder.getPayPrice().multiply(new BigDecimal("0.0065"));
			BigDecimal truthPrice = storeOrder.getPayPrice().subtract(hfServicePrice).setScale(2, RoundingMode.FLOOR);
			if(1 == totalPrice.compareTo(truthPrice)) {
				totalPrice = truthPrice;
			}
			
			log.info("--------------- 该订单{}进行分账业务, 实际支付金额: {}, 实际可分账金额: {}, 成本价总和: {}, 运税费总和: {}, 准备分账金额:{} ---------------", storeOrder.getOrderId(), storeOrder.getPayPrice(), truthPrice, totalCostPrice, totalTaxPrice, totalPrice);
			JSONObject resultObj = adapayDegreePayOrderProcess.transDiv(storeOrder.getOrderId(), storeOrder.getOutOrderId(), totalPrice, Constants.HF_USER_ID, storeOrder.getMerId());
			log.info("--------------- 该订单{}进行分账业务, 返回结果: {} ---------------", storeOrder.getOrderId(), resultObj.toJSONString());
			String respCode = resultObj.getString("respCode"); // 状态码
			String requestId = resultObj.getString("requestId"); // 请求流水号
			String requestTime = resultObj.getString("requestTime"); // 请求时间
			String dealId = resultObj.getString("dealId"); // 交易单号
			String ext1 = resultObj.getString("ext1"); // 扩展字段
			String respMsg = null;
			String details = null;
			boolean status = false;
			// 成功
			if(Constants.HTTPSTATUS_CODE_SUCCESS_STRING.equals(respCode)) {
				log.info("--------------- 该订单{}进行分账业务, 请求成功 ---------------", storeOrder.getOrderId());
				status = true;
				storeOrderService.update(Wrappers.lambdaUpdate(StoreOrder.class)
						.eq(StoreOrder :: getId, storeOrder.getId())
						.set(StoreOrder :: getTransBackParam, resultObj.toString())
						);
			// 失败
			} else {
				respMsg = resultObj.get("requestTime") + ""; //错误描述
				details = resultObj.get("details") + ""; // 错误明细
				log.info("--------------- 该订单{}进行分账业务, 请求失败: {} ---------------", storeOrder.getOrderId(), resultObj);
			}
			
			// 流水记录开始
			StoreOrderTrans storeOrderTrans = new StoreOrderTrans();
			storeOrderTrans.setMerId(storeOrder.getMerId());
			storeOrderTrans.setOrderId(storeOrder.getOrderId());
			storeOrderTrans.setInfoId(infoIds.toString());
			storeOrderTrans.setStatus(status);
			storeOrderTrans.setTotalCostPrice(totalCostPrice);
			storeOrderTrans.setTotalTaxPrice(totalTaxPrice);
			storeOrderTrans.setRequestId(requestId);
			storeOrderTrans.setRequestTime(requestTime);
			storeOrderTrans.setDealId(dealId);
			storeOrderTrans.setExt1(ext1);
			storeOrderTrans.setRespMsg(respMsg);
			storeOrderTrans.setDetail(details);
			//保存到数据库
			storeOrderTransService.save(storeOrderTrans);
		} catch (Exception e) {
			e.printStackTrace();
		}

    }

    /**
     * 记录商品支付数量
     * @param storeOrder 订单 storeOrderInfoList 子订单集合
     * @author duyb
     * @since 2020-10-19
     */
    @Override
    @Async("taskExecutor")
    public void saveAddPurchaseNumber(StoreOrder storeOrder,List<StoreOrderInfo> storeOrderInfoList) {
        for (StoreOrderInfo info : storeOrderInfoList) {
            StoreProduct storeProduct = storeProductService.getById(info.getProductId());
            StoreProductActive storeProductActive = storeSaleAnalysisService.getOne(Wrappers.<StoreProductActive>lambdaQuery()
                    .eq(StoreProductActive::getMerId, storeOrder.getMerId())
                    .eq(StoreProductActive::getProductId, info.getProductId())
                    .eq(StoreProductActive::getStatisticsDate, DateUtil.nowDateTimeReturnDate("yyyy-MM-dd"))
            );
            if (storeProductActive == null) {
                storeProductActive = new StoreProductActive();
                storeProductActive.setMerId(storeOrder.getMerId());
                storeProductActive.setProductId(info.getProductId());
                storeProductActive.setStoreName(storeProduct.getStoreName());
                storeProductActive.setCreateTime(DateUtil.nowDateTime());
                storeProductActive.setPayProductNumber(1);
                storeProductActive.setPaymentAmount(info.getPayPrice());
                storeProductActive.setStatisticsDate(DateUtil.nowDateTimeReturnDate("yyyy-MM-dd"));
            } else {
                storeProductActive.setPayProductNumber(storeProductActive.getPayProductNumber() + 1);
                storeProductActive.setPaymentAmount(storeProductActive.getPaymentAmount().add(info.getPayPrice()));
            }
            storeSaleAnalysisService.saveOrUpdate(storeProductActive);
        }
    }



    /**
     * 删除已完成订单
     *
     * @param id Integer 订单id
     * @return 计算后的价格集合
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public Boolean delete(Integer id) {
        try {
            StoreOrder storeOrder = orderUtils.getInfoById(id);
            if (null == storeOrder) {
                throw new CrmebException("订单不存在!");
            }
            if (Constants.ORDER_STATUS_H5_CANCEL != storeOrder.getStatus() && Constants.ORDER_STATUS_H5_REFUNDED != storeOrder.getStatus() && Constants.ORDER_STATUS_H5_COMPLETE != storeOrder.getStatus()) {
                throw new CrmebException("该订单无法删除,只允许删除已取消、已退款和已完成");
            }
            //可以删除
            storeOrder.setIsDel(true);
            boolean result = storeOrderService.updateById(storeOrder);

            //删除子订单
            storeOrderInfoService.update(Wrappers.lambdaUpdate(StoreOrderInfo.class).eq(StoreOrderInfo::getOrderId, storeOrder.getId()).set(StoreOrderInfo::getIsDel, 1));

            // 批采子订单
            storeOrderInfoPickingService.update(Wrappers.<StoreOrderInfoPicking>lambdaUpdate().eq(StoreOrderInfoPicking::getOrderId, storeOrder.getId()).set(StoreOrderInfoPicking::getIsDel, 1));

            //后续操作放入redis
            redisUtil.lPush(Constants.ORDER_TASK_REDIS_KEY_AFTER_DELETE_BY_USER, id);

            return result;

        } catch (Exception e) {
            throw new CrmebException("删除失败 " + e.getMessage());
        }

    }

    /**
     * 订单评价
     *
     * @param request StoreProductReplyAddRequest 评论信息
     */
    @Override
    public boolean reply(StoreProductReplyAddRequest request) {
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setId(request.getOid());
        storeOrderPram.setUid(userService.getUserIdException());
        StoreOrder existStoreOrder = storeOrderService.getByEntityOne(storeOrderPram);
        if (null == existStoreOrder)
            throw new CrmebException("该订单不存在");
        return storeProductReplyService.create(request);
    }

    /**
     * 订单收货
     *
     * @param id Integer 订单id
     */
    @Override
    public boolean take(Integer id) {
        try {
//            StoreOrder storeOrder = orderUtils.getInfoById(id);
            StoreOrderInfo storeOrderInfo = orderUtils.getStoreOrderInfoById(id);
            if (!storeOrderInfo.getStatus().equals(Constants.ORDER_STATUS_H5_SPIKE)) {
                throw new CrmebException("订单状态错误");
            }
            //已收货，待评价
            storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_COMPLETE);
            boolean result = storeOrderInfoService.updateById(storeOrderInfo);
//            boolean result = storeOrderService.updateById(storeOrder);
            if (result) {
                storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), "confirm_receipt", "用户确认收货");
                orderUtils.updateOrderStatus(storeOrderInfo.getOrderId());
            }
            return result;
        } catch (Exception e) {
            throw new CrmebException("收货失败" + e.getMessage());
        }
    }

    @Override
    public void batchTake() {
        List<StoreOrder> storeOrders = storeOrderService.list(Wrappers.<StoreOrder>lambdaQuery().select(StoreOrder::getId).eq(StoreOrder::getStatus, OrderStatusEnum.SHIPPED.getCode()).apply("datediff(NOW(), create_time) >= 30"));
        for (StoreOrder storeOrder : storeOrders) {
            storeOrderService.update(Wrappers.<StoreOrder>lambdaUpdate().eq(StoreOrder::getId, storeOrder.getId()).set(StoreOrder::getStatus, Constants.ORDER_STATUS_H5_COMPLETE));
            //后续操作放入redis
            redisUtil.lPush(Constants.ORDER_TASK_REDIS_KEY_AFTER_TAKE_BY_SYSTEM, storeOrder.getId());
        }
    }

    /**
     * 订单取消
     *
     * @param id Integer 订单id
     */
    @Override
    public boolean cancel(Integer id) {
        StoreOrder storeOrder = orderUtils.getInfoById(id);
        // 不走异步，直接退
        boolean result = storeOrderTaskService.cancelByUser(storeOrder, false);
        /*if(result){
            weChatPayService.closeOrder(storeOrder.getOrderId());
        }*/
        // 关闭支付单
        //后续操作放入redis
        //        redisUtil.lPush(Constants.ORDER_TASK_REDIS_KEY_AFTER_CANCEL_BY_USER, id);
        return result;
    }

    /**
     * 订单超时1小时候自动取消
     *
     * @param storeOrder
     */
    @Override
    public boolean cancel(StoreOrder storeOrder) {
        //StoreOrder storeOrder = orderUtils.getInfoById(id);
        // 不走异步，直接退
        boolean result = storeOrderTaskService.cancelByUser(storeOrder, true);
        /*if(result){
            weChatPayService.closeOrder(storeOrder.getOrderId());
        }*/
        // 关闭支付单
        //后续操作放入redis
        //        redisUtil.lPush(Constants.ORDER_TASK_REDIS_KEY_AFTER_CANCEL_BY_USER, id);
        return result;
    }

    /**
     * 订单退款前验证
     *
     * @param request 退款参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean refundVerify(OrderRefundVerifyRequest request) {
        int retryCount = 0;
        while (retryCount < 3) {
            try {
                return performRefundVerify(request);
            } catch (DeadlockLoserDataAccessException e) {
                retryCount++;
                if (retryCount >= 3) {
                    throw e;
                }
            }
        }
        return false;
    }

    private boolean performRefundVerify(OrderRefundVerifyRequest request) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getId());
        if (null == storeOrderInfo) {
            throw new CrmebException("支付订单不存在");
        }
        if (storeOrderInfo.getRefundStatus() == 2) {
            throw new CrmebException("订单已退款");
        }
        if (storeOrderInfo.getRefundStatus() == 1) {
            throw new CrmebException("正在申请退款中");
        }
        if (storeOrderInfo.getStatus() == 0 || storeOrderInfo.getStatus() == 4 || storeOrderInfo.getStatus() == 5) {
            throw new CrmebException("当前订单状态无法申请退款");
        }
        int count = storeOrderRefundApplyService.count(Wrappers.<StoreOrderRefundApply>lambdaQuery().eq(StoreOrderRefundApply::getInfoId, request.getId()));
        if (count >= 2) {
            throw new CrmebException("同一笔订单仅可以申请2次退款");
        }
        String message = "用户申请退款原因：" + request.getText();
        if (StringUtils.isNotBlank(request.getRefund_reason_wap_explain())) {
            message = message + "；备注：" + request.getRefund_reason_wap_explain();
        }
        storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_LOG_REFUND_APPLY, message);
        Integer status = storeOrderInfo.getStatus();
        storeOrderInfo.setRefundStatus(1);
        storeOrderInfo.setStatus(-1);
        storeOrderInfo.setRefundReasonTime(DateUtil.nowDateTime());
        storeOrderInfo.setRefundReasonWap(request.getText());
        storeOrderInfo.setRefundReasonWapExplain(request.getRefund_reason_wap_explain());
        storeOrderInfo.setRefundReasonWapImg(systemAttachmentService.clearPrefix(request.getRefund_reason_wap_img()));

        boolean updateOrderResult = storeOrderInfoService.updateById(storeOrderInfo);

        StoreOrderRefundApply storeOrderRefundApply = new StoreOrderRefundApply();
        storeOrderRefundApply.setOldStatus(status);
        storeOrderRefundApply.setInfoId(request.getId());
        storeOrderRefundApply.setRefundType(request.getRefundType());
        storeOrderRefundApply.setRefundReasonTime(DateUtil.nowDateTime());
        storeOrderRefundApply.setRefundReasonWap(request.getText());
        storeOrderRefundApply.setRefundReasonWapExplain(request.getRefund_reason_wap_explain());
        storeOrderRefundApply.setRefundReasonWapImg(systemAttachmentService.clearPrefix(request.getRefund_reason_wap_img()));
        storeOrderRefundApplyService.save(storeOrderRefundApply);

        // 移除用户拼团信息
        StoreOrder storeOrder = storeOrderService.getById(storeOrderInfo.getOrderId());
        if (Objects.nonNull(storeOrder.getActivityGroupId())){
            storeOrderGroupInfoService.removeGroupInfo(storeOrder);
        }
        if (!updateOrderResult) {
            throw new CrmebException("申请退款失败");
        }
        return true;
    }

    /**
     * 订单退款申请
     *
     * @param request OrderRefundApplyRequest 退款参数
     */
    @Override
    public boolean refundApply(OrderRefundApplyRequest request) {
        StoreOrderInfo storeOrderInfo = orderUtils.getStoreOrderInfoById(request.getId());
        if (storeOrderInfo.getRefundStatus() == 1) {
            throw new CrmebException("正在申请退款中");
        }

        if (storeOrderInfo.getRefundStatus() == 2) {
            throw new CrmebException("订单已退款");
        }

        if (storeOrderInfo.getStatus() != 6) {
            throw new CrmebException("订单当前无法退款");
        }
        StoreCartResponse response = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);

        storeOrderInfo.setRefundReasonWapImg(systemAttachmentService.clearPrefix(request.getReasonImage()));
        storeOrderInfo.setRefundStatus(1);
        storeOrderInfo.setRefundReasonWapExplain(request.getExplain());
        storeOrderInfo.setRefundReason(request.getText());
        storeOrderInfo.setRefundPrice(response.getProductInfo().getAttrInfo().getPaidPrice());
        storeOrderInfo.setRefundReasonTime(DateUtil.nowDateTime());
        boolean b = storeOrderInfoService.updateById(storeOrderInfo);
        // 移除用户拼团信息
        if (b){
            StoreOrder storeOrder = storeOrderService.getById(storeOrderInfo.getOrderId());
            if (Objects.nonNull(storeOrder.getActivityGroupId())){
                storeOrderGroupInfoService.removeGroupInfo(storeOrder);
            }
        }
        return b;



//        StoreOrder storeOrder = orderUtils.getInfoById(request.getId());
//        if (storeOrder.getRefundStatus() == 1) {
//            throw new CrmebException("正在申请退款中");
//        }
//
//        if (storeOrder.getRefundStatus() == 2) {
//            throw new CrmebException("订单已退款");
//        }
//
//        if (storeOrder.getStatus() == 1) {
//            throw new CrmebException("订单当前无法退款");
//        }
//        storeOrder.setRefundReasonWapImg(systemAttachmentService.clearPrefix(request.getReasonImage()));
//        storeOrder.setRefundStatus(1);
//        storeOrder.setRefundReasonWapExplain(request.getExplain());
//        storeOrder.setRefundReason(request.getText());
//        storeOrder.setRefundPrice(storeOrder.getPayPrice());
//        storeOrder.setRefundReasonTime(DateUtil.nowDateTime());
//        return storeOrderService.updateById(storeOrder);
    }

    /**
     * 再次下单
     *
     * @param request 参数
     * @return 下单结果
     */
    @Override
    public HashMap<String, Object> againOrder(OrderAgainRequest request) {
        // 检查是否已经有相同的商品再次下单
        //        StoreCartResponse cacheOrderAgain = orderUtils.getCacheOrderAgain(request.getNui());
        //        if(null != cacheOrderAgain) throw new CrmebException("已经有相同的订单存在");

        HashMap<String, Object> resultMap = new HashMap<>();
        User currentUser = userService.getInfo();
        StoreOrder storeOrder = new StoreOrder();
        storeOrder.setUid(currentUser.getUid());
        storeOrder.setUnique(request.getNui());
        StoreOrder storeOrderExist = storeOrderService.getInfoByEntity(storeOrder);
        if (null == storeOrderExist)
            throw new CrmebException("订单不存在");
        OrderAgainVo orderAgainVo = orderUtils.tidyOrder(storeOrderExist, true, false);
        //        List<StoreCart> storeCartResultList = new ArrayList<>();
        for (StoreOrderInfoVo oldCartInfo : orderAgainVo.getCartInfo()) { // todo 确实是否仅仅一条数据
            // todo 营销产品类型二期
            List<String> orderAgainCacheKeys = storeOrderService.addCartAgain(userService.getUserIdException(), oldCartInfo.getProductId(), oldCartInfo.getInfo().getCartNum(), storeOrderExist.getUnique(), oldCartInfo.getInfo().getType(), true, oldCartInfo.getInfo().getCombinationId(), oldCartInfo.getInfo().getSeckillId(), oldCartInfo.getInfo().getBargainId());
            resultMap.put("cateId", orderAgainCacheKeys.get(0));

        }
        if (resultMap.size() == 0)
            throw new CrmebException("再来一单失败，请重新下单");
        //        resultMap.put("cateId",storeCartResultList.stream().map(StoreCart::getId).distinct().collect(Collectors.toList()));
        return resultMap;
    }

    /**
     * 支付订单
     *
     * @param request 支付参数
     * @return 支付结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
//    @Transactional(rollbackFor = { RuntimeException.class, Error.class, CrmebException.class })
    public Map<String, Object> payOrder(OrderPayRequest request, String ip) {
        String lockKey = "order_id:" + request.getUni();
        RLock rLock = redisson.getLock(lockKey);
        try {
            if (!rLock.tryLock()) {
                throw new CrmebException("该订单正在支付中!");
            }
            log.info("用户待付款支付订单: {}", JSON.toJSONString(request));
            if (-1 != yueMerIds.indexOf(request.getMerId()) && Constants.PAY_TYPE_YUE.equals(request.getPaytype())) {
                throw new CrmebException("该商户余额支付功能已关闭");
            }

            // 获取支付渠道
            Integer type = orderUtils.getOrderPayType(request.getMerId()).getCode();
            IOrderProcess orderProcess = commonFactory.getOrderType(type);

            ExecutorService thread = ThreadPoolUtils.getThread();
            thread.execute(()->{
                DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,JSON.toJSONString(request)+ip);
            });
            return orderProcess.toPayOrder(request, ip);
        } finally {
            if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                rLock.unlock();
            }
        }
    }

    /**
     * 连连支付海关推单
     */
    @Override
    public Map<String, Object> toPushPayOrder(StoreOrder storeOrder, String ip) {
        log.info("支付：连连支付海关推单 toPayOrder：{},{}", JSONObject.toJSONString(storeOrder), ip);
//		//支付调用请求
        Map<String, Object> resultMap = new HashMap<>();
//		Map<String, Object> result = payPayment(order, ip, Constants.SERVICE_PAY_TYPE_ORDER);
//
        resultMap.put("orderId", storeOrder.getOrderId());
        resultMap.put("orderStatus", storeOrder.getStatus());
        resultMap.put("status", Constants.LIANLIAN_DEGREE_PAY);

        // 下单成功异步触发支付单申报
        CompletableFuture.runAsync(()->{
            List<StoreOrderInfo> list = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, storeOrder.getId()));
            if (org.apache.commons.collections.CollectionUtils.isEmpty(list)){
                return;
            }
            List<Integer> orderInfoIds = list.stream().map(StoreOrderInfo::getId).collect(Collectors.toList());
            String pushResult = "";
            try {
                Thread.sleep(30*1000);
                pushResult = storeOrderService.pushLianlianCustoms(orderInfoIds);
            }catch (Exception e){
                pushResult = e.getCause()+e.getMessage();
                log.error("自动推送支付单失败（连连）:",e);
            }
            DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,String.format("支付单自动申报结果（连连）:%S,%s",storeOrder.getOrderId(),pushResult));
        });

        return resultMap;
    }

    /**
     * 查询订单状态
     *
     * @param request 查询订单状态参数
     * @return 查询订单状态结果
     */
    @Override
    public Map<String, Object> getOrderStatus(OrderQueryRequest request) {
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setOrderId(request.getOrderId());
        storeOrderPram.setIsDel(false);
        StoreOrder existStoreOrder = storeOrderService.getInfoByEntity(storeOrderPram);

        Map<String, Object> map = new HashMap<>(Constants.NUM_ONE);
        if(null != existStoreOrder){
            map.put("orderStatus", existStoreOrder.getPaid());
        }
        return map;
    }

    /**
     * 支付订单
     *
     * @param
     * @return 支付结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
//    @Transactional(rollbackFor = { RuntimeException.class, Error.class, CrmebException.class })
    public boolean payTest() {

        // 发送消息通知和短信提醒
        messageConfigService.sendWarningMessage(1);

        return true;
    }

    /**
     * 订单列表
     * @param status      类型
     * @param searchWord  搜索条件: 商品名/订单号
     * @param pageRequest 分页
     */
    @Override
    public CommonPage<OrderAgainVo> list(Integer status, String searchWord, PageParamRequest pageRequest) {
        //        PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        List<OrderAgainVo> listResponses = new ArrayList<>();
        User currentUser = userService.getInfo();
        StoreOrder storeOrderPram = new StoreOrder();
        //        storeOrderPram.setStatus(status);
        storeOrderPram.setUid(currentUser.getUid());
        //        storeOrderPram.setIsDel(false);
        //        storeOrderPram.setIsSystemDel(false);
        storeOrderPram.setStatus(status);
        storeOrderPram.setPickingId(0);
        storeOrderPram.setOrderId(searchWord);
        storeOrderPram.setProductName(searchWord);
//        List<StoreOrder> orderList = storeOrderService.getUserOrderList(storeOrderPram, pageRequest);
        //查询子订单
        getChildOrderListRequest(storeOrderPram);
        Page<Object> page = PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        List<StoreOrderInfo> storeOrderInfoList = storeOrderInfoService.getUserOrderList(storeOrderPram);
        if (CollectionUtils.isEmpty(storeOrderInfoList)) {
            return CommonPage.restPage(CommonPage.copyPageInfo(page, listResponses));
        }
        Map<Integer, List<StoreOrderInfo>> listMap = storeOrderInfoList.stream().collect(Collectors.groupingBy(StoreOrderInfo::getOrderId));
        //退款时间
        QueryWrapper<StoreOrderStatus> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("oid,order_number,MAX(create_time) as create_time");
        queryWrapper.eq("change_type", Constants.ORDER_LOG_REFUND_PRICE).notLike("change_message", "失败")
                .in("oid", listMap.keySet())
                .groupBy("oid,order_number");
        List<StoreOrderStatus> refundList = storeOrderStatusService.list(queryWrapper);
        Map<Integer, StoreOrderStatus> refundMap = refundList.stream().filter(e -> e.getOrderNumber() == null).collect(Collectors.toMap(StoreOrderStatus::getOid, e -> e));
        Map<String, StoreOrderStatus> childRefundMap = refundList.stream().filter(e -> e.getOrderNumber() != null).collect(Collectors.toMap(StoreOrderStatus::getOrderNumber, e -> e));
        for (Map.Entry<Integer, List<StoreOrderInfo>> entry : listMap.entrySet()) {
            OrderAgainVo orderAgainVo = new OrderAgainVo();
            StoreOrder storeOrder = storeOrderService.getById(entry.getKey());
            orderAgainVo.setStoreOrder(storeOrder);
            List<StoreOrderInfoVo> cartInfo = new ArrayList<>();
            for (StoreOrderInfo storeOrderInfo : entry.getValue()) {
                //解析商品详情JSON
                StoreOrderInfoVo StoreOrderInfoVo = new StoreOrderInfoVo();
                BeanUtils.copyProperties(storeOrderInfo, StoreOrderInfoVo, "info");
                StoreOrderInfoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
                StoreOrderInfoVo.getInfo().setIsReply(
                        storeProductReplyService.isReply(StoreOrderInfoVo.getUnique(), "product", StoreOrderInfoVo.getOrderId()).size()
                );
                StoreOrderStatus storeOrderStatus = childRefundMap.get(storeOrderInfo.getChildOrderNumber());
                if (null != storeOrderStatus) {
                    StoreOrderInfoVo.setRefundReasonTime(storeOrderStatus.getCreateTime());
                } else {
                    StoreOrderStatus orderStatus = refundMap.get(storeOrder.getId());
                    if (null != orderStatus) {
                        StoreOrderInfoVo.setRefundReasonTime(orderStatus.getCreateTime());
                    }
                }
                cartInfo.add(StoreOrderInfoVo);
            }
            orderAgainVo.setCartInfo(cartInfo);
            orderAgainVo.setCreatTime(storeOrder.getCreateTime());
            orderAgainVo.setAddressChange(false);
            if (storeOrder.getStatus().equals(OrderStatusEnum.UNPAID.getCode())) {
                int flag = storeOrderStatusService.count(Wrappers.lambdaQuery(StoreOrderStatus.class).eq(StoreOrderStatus::getOid, storeOrder.getId()).eq(StoreOrderStatus::getChangeType, Constants.ORDER_USER_UPDATE_ADDRESS));
                orderAgainVo.setAddressChange(flag < 1);
            }
            if (Objects.nonNull(storeOrder.getActivityGroupId())){
                StoreOrderGroupInfo one = storeOrderGroupInfoService.getById(storeOrder.getActivityGroupId());
                if (Objects.isNull(one) || one.getStatus()){
                    orderAgainVo.setGroupMsg(null);
                } else {
                    orderAgainVo.setGroupMsg(StrUtil.format("还差{}人拼团", one.getProductGroupNumber() - one.getUids().split(",").length));
                }
            }
            listResponses.add(orderAgainVo);
        }
        List<OrderAgainVo> againVoList = listResponses.stream().sorted(Comparator.comparing(OrderAgainVo::getCreatTime).reversed()).collect(Collectors.toList());
        return CommonPage.restPage(CommonPage.copyPageInfo(page, againVoList));
    }

    @Override
    public CommonPage<OrderAgainVo> pickingOrderList(Integer status, String orderNo, PageParamRequest pageRequest) {
        List<OrderAgainVo> listResponses = new ArrayList<>();
        User currentUser = userService.getInfo();
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setUid(currentUser.getUid());
        storeOrderPram.setStatus(status);
        storeOrderPram.setOrderId(orderNo);
        //查询子订单
        List<StoreOrderInfo> storeOrderInfoList = new ArrayList<>();
        Page<Object> page = PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        if (status == 9) {
            //全部
            storeOrderInfoList = storeOrderInfoService.getUnionAllOrderInfo(storeOrderPram);
        } else if (status == 0) {
            //待核实
            storeOrderInfoList = storeOrderInfoService.getVerifyOrderInfo(storeOrderPram);
        } else {
            getChildOrderListRequest(storeOrderPram);
            storeOrderInfoList = storeOrderInfoService.getUserOrderList(storeOrderPram);
        }
        if (CollectionUtils.isEmpty(storeOrderInfoList)) {
            return CommonPage.restPage(CommonPage.copyPageInfo(page, listResponses));
        }
        Map<Integer, List<StoreOrderInfo>> listMap = storeOrderInfoList.stream().collect(Collectors.groupingBy(StoreOrderInfo::getOrderId));
        //退款时间
        QueryWrapper<StoreOrderStatus> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("oid,order_number,MAX(create_time) as create_time");
        queryWrapper.eq("change_type", Constants.ORDER_LOG_REFUND_PRICE).notLike("change_message", "失败")
                .in("oid", listMap.keySet())
                .groupBy("oid,order_number");
        List<StoreOrderStatus> refundList = storeOrderStatusService.list(queryWrapper);
        Map<Integer, StoreOrderStatus> refundMap = refundList.stream().filter(e -> e.getOrderNumber() == null).collect(Collectors.toMap(StoreOrderStatus::getOid, e -> e));
        Map<String, StoreOrderStatus> childRefundMap = refundList.stream().filter(e -> e.getOrderNumber() != null).collect(Collectors.toMap(StoreOrderStatus::getOrderNumber, e -> e));
        for (Map.Entry<Integer, List<StoreOrderInfo>> entry : listMap.entrySet()) {
            OrderAgainVo orderAgainVo = new OrderAgainVo();
            StoreOrder storeOrder = storeOrderService.getById(entry.getKey());
            orderAgainVo.setStoreOrder(storeOrder);
            List<StoreOrderInfoVo> cartInfo = new ArrayList<>();
            for (StoreOrderInfo storeOrderInfo : entry.getValue()) {
                //解析商品详情JSON
                StoreOrderInfoVo StoreOrderInfoVo = new StoreOrderInfoVo();
                BeanUtils.copyProperties(storeOrderInfo, StoreOrderInfoVo, "info");
                StoreOrderInfoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
                StoreOrderInfoVo.getInfo().setIsReply(
                        storeProductReplyService.isReply(StoreOrderInfoVo.getUnique(), "product", StoreOrderInfoVo.getOrderId()).size()
                );
                StoreOrderStatus storeOrderStatus = childRefundMap.get(storeOrderInfo.getChildOrderNumber());
                if (null != storeOrderStatus) {
                    StoreOrderInfoVo.setRefundReasonTime(storeOrderStatus.getCreateTime());
                } else {
                    StoreOrderStatus orderStatus = refundMap.get(storeOrder.getId());
                    if (null != orderStatus) {
                        StoreOrderInfoVo.setRefundReasonTime(orderStatus.getCreateTime());
                    }
                }
                if (StoreOrderInfoVo.getNum() == null) {
                    StoreOrderInfoVo.setNum(1);
                }
                cartInfo.add(StoreOrderInfoVo);
            }
            orderAgainVo.setCartInfo(cartInfo);
            orderAgainVo.setCreatTime(storeOrder.getCreateTime());
            orderAgainVo.setAddressChange(false);
            if (storeOrder.getStatus().equals(OrderStatusEnum.UNPAID.getCode()) || storeOrder.getStatus().equals(OrderStatusEnum.VERIFY.getCode())) {
                int flag = storeOrderStatusService.count(Wrappers.lambdaQuery(StoreOrderStatus.class).eq(StoreOrderStatus::getOid, storeOrder.getId()).eq(StoreOrderStatus::getChangeType, Constants.ORDER_USER_UPDATE_ADDRESS));
                orderAgainVo.setAddressChange(flag < 1);
            }
            listResponses.add(orderAgainVo);
        }
        List<OrderAgainVo> againVoList = listResponses.stream().sorted(Comparator.comparing(OrderAgainVo::getCreatTime).reversed()).collect(Collectors.toList());
        return CommonPage.restPage(CommonPage.copyPageInfo(page, againVoList));
    }

    private void getChildOrderListRequest(StoreOrder storeOrderPram) {
        String where = " o.is_del = 0 and o.uid =" + storeOrderPram.getUid();
        if (Objects.equals(storeOrderPram.getPickingId(), 0)) {
            where += " and o.picking_id = 0 ";
        } else {
            where += " and o.picking_id != 0 ";
        }
        if (StringUtils.isNotBlank(storeOrderPram.getOrderId())) {
            where += " and ( o.order_id = '" + storeOrderPram.getOrderId() + "' or i.child_order_number = '" + storeOrderPram.getOrderId() + "' or p.store_name like '%" + storeOrderPram.getProductName() + "%')";
        }
        Integer status = storeOrderPram.getStatus();
        if (null != status) {
            List<Integer> orderStatusList = new ArrayList<>();
            switch (status) {
                //待付款
                case 1:
                    orderStatusList.add(0);
                    break;
                //待确认
                case 2:
                    orderStatusList.add(6);
                    break;
                //待发货
                case 3:
                    orderStatusList.add(1);
                    break;
                //待收货
                case 4:
                    orderStatusList.add(2);
                    break;
                //已完成
                case 5:
                    orderStatusList.add(4);
                    break;
                //售后（退款中，已退款）
                case 6:
                    orderStatusList.add(-1);
                    orderStatusList.add(-2);
                    break;
                case 7:
                    orderStatusList.add(5);
                    break;
                //全部（包括1.2.3.4.5.6以及已取消)
                case 9:
                    orderStatusList = Stream.of(0, 1, 2, 4, 5, 6, -1, -2).collect(Collectors.toList());
                    break;
                default:
                    //其他传状态不存在的null
                    orderStatusList.add(null);
                    break;
            }
            if (CollectionUtils.isNotEmpty(orderStatusList)) {
                if (orderStatusList.size() == 1) {
                    where += " and i.status  = " + orderStatusList.get(0);
                } else {
                    where += " and i.status in " + orderStatusList.toString().replace("[", "(").replace("]", ")");
                }
            }
        }
        storeOrderPram.setWhere(where);
    }


    /**
     * 订单详情
     *
     * @param orderId 订单id
     */
    @Override
    public StoreOrderDetailResponse detailOrder(String orderId) {
        StoreOrderDetailResponse storeOrderDetailResponse = new StoreOrderDetailResponse();
        Map<String, Object> discountInfo = new HashMap<>();
        User currentUser = userService.getInfo();
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setUid(currentUser.getUid());
        storeOrderPram.setUnique(orderId);
        storeOrderPram.setIsDel(false);
        StoreOrder storeOrderResult = storeOrderService.getInfoJustOrderInfo(storeOrderPram);
        if (null == storeOrderResult)
            throw new CrmebException("订单不存在");

        BeanUtils.copyProperties(storeOrderResult, storeOrderDetailResponse);
        StoreCouponUser storeCouponUser = Optional.ofNullable(storeCouponUserService.getById(storeOrderResult.getCouponId())).orElse(new StoreCouponUser());
        storeOrderDetailResponse.setCouponName(storeCouponUser.getName());
        Date dateY = DateUtil.strToDate(storeOrderResult.getCreateTime().toString(), Constants.DATE_FORMAT_DATE);
        Date dateH = DateUtil.strToDate(storeOrderResult.getCreateTime().toString(), Constants.DATE_FORMAT_HHMMSS);
        storeOrderDetailResponse.setAddTimeH(dateY);
        storeOrderDetailResponse.setAddTimeH(dateH);
        SystemStore systemStorePram = new SystemStore();
        systemStorePram.setIsShow(true);
        systemStorePram.setIsDel(false);
        systemStorePram.setId(storeOrderResult.getStoreId());
        storeOrderDetailResponse.setSystemStore(systemStoreService.getByCondition(systemStorePram));
        storeOrderDetailResponse.setAddressChange(false);
        if (storeOrderResult.getStatus().equals(OrderStatusEnum.UNPAID.getCode()) || storeOrderResult.getStatus().equals(OrderStatusEnum.VERIFY.getCode())) {
            int flag = storeOrderStatusService.count(Wrappers.lambdaQuery(StoreOrderStatus.class).eq(StoreOrderStatus::getOid, storeOrderResult.getId()).eq(StoreOrderStatus::getChangeType, Constants.ORDER_USER_UPDATE_ADDRESS));
            storeOrderDetailResponse.setAddressChange(flag < 1);
        }
        if (storeOrderResult.getShippingType() == 3 && storeOrderResult.getVerifyCode().length() > 0) {
            String name = storeOrderResult.getVerifyCode() + ".jpg";
            SystemAttachment systemAttachmentPram = new SystemAttachment();
            systemAttachmentPram.setName(name);
            // todo 二维码前端生成
        }
        storeOrderDetailResponse.setMapKey(systemConfigService.getValueByKey("tengxun_map_key"));
        //        StoreOrder storeOrder = new StoreOrder();
        //        BeanUtils.copyProperties(storeOrderDetailResponse,storeOrder);
        OrderAgainVo orderAgainVo = orderUtils.tidyOrder(storeOrderResult, true, true);
        BeanUtils.copyProperties(orderAgainVo.getStoreOrder(), storeOrderDetailResponse);
        List<StoreOrderInfoVo> cartInfo = orderAgainVo.getCartInfo();
        //待核实查询商品上下架状态
        List<Integer> isShowProductIdList = new ArrayList<>();
        if (Objects.equals(storeOrderResult.getStatus(), OrderStatusEnum.VERIFY.getCode())) {
            List<Integer> productIdList = cartInfo.stream().map(StoreOrderInfoVo::getProductId).distinct().collect(Collectors.toList());
            //查询上架状态商品
            isShowProductIdList = storeProductService.getIsShowProducts(productIdList, storeOrderResult.getMerId());
        }
        for (StoreOrderInfoVo info : cartInfo) {
            // 满减送信息
            discountInfo = info.getInfo().getDiscountInfo();
            OrderInfoDelivery orderInfoDelivery = null;
            if (!BooleanUtils.isTrue(info.getIsVirtual())) {
                orderInfoDelivery = orderInfoDeliveryService.selectDeliveryByOrderInfoId(info.getId());
            }
            DeliveryResponse response = new DeliveryResponse();
            if (null != orderInfoDelivery) {
                DeliveryRequest request = new DeliveryRequest();
                request.setCom(orderInfoDelivery.getDeliveryCode());
                request.setDeliveryNumber(orderInfoDelivery.getDeliveryNumber());
                request.setPhone(orderInfoDelivery.getPhone());
                request.setOrderInfoId(info.getId());
                response = orderInfoDeliveryService.queryDeliveryByShowApi(request, orderInfoDelivery);
                if (null != response) {
                    response.setLevel(orderInfoDelivery.getLevel());
                    // 用户小程序已完成订单显示物流查询按钮
                    if (OrderStatusEnum.COMPLETE.getCode().equals(info.getStatus())) {
                        response.setStatus(1);
                    }
                } else {
                    response = new DeliveryResponse();
                    response.setStatus(1);
                    response.setLevel(orderInfoDelivery.getLevel());
                }
            } else {
                response.setStatus(0);
                response.setLevel(0);
            }
            info.setDelivery(response);
            if (StringUtils.isBlank(info.getInfo().getDeliveryTime())) {
                info.getInfo().setDeliveryTime(productUtil.getDeliveryTimeByTempId(info.getInfo().getProductInfo().getTempId(), info.getInfo().getProductInfo().getIsEurope(), storeOrderResult.getMerId(), info.getInfo().getProductInfo().getId()));
            }
            if (StringUtils.isBlank(info.getInfo().getReceivingTime())) {
                info.getInfo().setReceivingTime(productUtil.getReceivingTime(info.getInfo().getProductInfo().getTempId(), info.getInfo().getProductInfo().getIsEurope(), storeOrderResult.getMerId(), info.getInfo().getProductInfo().getId()));
            }
            List<StoreOrderStatus> storeOrderStatusList = storeOrderStatusService.list(Wrappers.lambdaQuery(StoreOrderStatus.class).eq(StoreOrderStatus::getChangeType, Constants.ORDER_LOG_REFUND_PRICE)
                    .like(StoreOrderStatus::getChangeMessage, "补偿性退款").notLike(StoreOrderStatus::getChangeMessage, "失败").eq(StoreOrderStatus::getOrderNumber, info.getChildOrderNumber()));
            if (CollectionUtils.isNotEmpty(storeOrderStatusList)) {
                List<BigDecimal> refundPriceList = new ArrayList<>();
                storeOrderStatusList.forEach(e -> {
                    refundPriceList.add(new BigDecimal(e.getChangeMessage().substring(e.getChangeMessage().indexOf("用户") + 2, e.getChangeMessage().indexOf("元"))));
                });
                info.setRefundPriceList(refundPriceList);
            }
            //退款时间
            StoreOrderStatus storeOrderStatus = Optional.ofNullable(storeOrderStatusService.getOne(Wrappers.lambdaQuery(StoreOrderStatus.class).eq(StoreOrderStatus::getChangeType, Constants.ORDER_LOG_REFUND_PRICE)
                    .like(StoreOrderStatus::getChangeMessage, "退货退款").notLike(StoreOrderStatus::getChangeMessage, "失败").eq(StoreOrderStatus::getOrderNumber, info.getChildOrderNumber()).last("LIMIT 1"))).orElse(new StoreOrderStatus());
            info.setRefundReasonTime(storeOrderStatus.getCreateTime());
            //差价
            StoreProductAttrValue attrInfo = info.getInfo().getProductInfo().getAttrInfo();
            if (attrInfo.getInitialPaidPrice() != null) {
                info.setChangePrice(attrInfo.getPaidPrice().subtract(attrInfo.getInitialPaidPrice()));
            }
            info.setIsShow(isShowProductIdList.contains(info.getProductId()));
            if (info.getId() != null) {
                List<StoreOrderRefundApply> applyList = storeOrderRefundApplyService.list(Wrappers.<StoreOrderRefundApply>lambdaQuery()
                        .eq(StoreOrderRefundApply::getInfoId, info.getId())
                        .orderByDesc(StoreOrderRefundApply::getId));
                info.setStoreOrderRefundApplyList(applyList);
            }
        }
        Integer totalNum = cartInfo.stream().mapToInt(info -> info.getInfo().getCartNum() == null ? 0 : info.getInfo().getCartNum()).sum();
        storeOrderDetailResponse.setTotalNum(totalNum);
        storeOrderDetailResponse.setCartInfo(cartInfo);
        storeOrderDetailResponse.setPStatus(orderAgainVo.getStatus());
        storeOrderDetailResponse.setStatusPic(orderAgainVo.getStatusPic());
        storeOrderDetailResponse.setDiscountInfo(discountInfo);
        // 处理门票订单标记
        handleActivityProduct(storeOrderDetailResponse,cartInfo.get(0).getProductId());
        return storeOrderDetailResponse;
    }

    private void handleActivityProduct(StoreOrderDetailResponse storeOrderDetailResponse,Integer productId) {
        KeyValueDO keyValueDO = keyValueService.getByTypeCodeAndKey("ACTIVITY_APPLY_PRODUCTS", "活动报名商品", false);
        if (null == keyValueDO || StringUtils.isBlank(keyValueDO.getValue())){
            return;
        }
        String[] productIds = keyValueDO.getValue().split(",");
        if (ArrayUtil.contains(productIds, String.valueOf(productId))){
            storeOrderDetailResponse.setIsActiveApplyProduct(1);
        }
    }

    /**
     * 订单tap data
     *
     * @return 订单状态数据量
     */
    @Override
    public OrderDataResponse orderData() {
        OrderDataResponse result = new OrderDataResponse();
        User currentUser = userService.getInfo();
        //1=待付款2=待确认3=待发货4=待收货5=已完成6=售后（退款中，已退款）9=全部（包括1.2.3.4.5.6以及已取消)
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setUid(currentUser.getUid());
        storeOrderPram.setPickingId(0);
        List<StoreOrderInfo> list = storeOrderInfoService.getOrderCount(storeOrderPram);
        Map<Integer, Integer> map = list.stream().collect(Collectors.toMap(StoreOrderInfo::getStatus, StoreOrderInfo::getId));
        int count = list.stream().mapToInt(StoreOrderInfo::getId).sum();
        //全部
        result.setAllCount(count);
        // 待付款
        result.setUnPaidCount(map.get(OrderStatusEnum.UNPAID.getCode()));
        //待确认
        result.setConfirmedCount(map.get(OrderStatusEnum.CONFIRM.getCode()));
        // 待发货
        result.setUnShippedCount(map.get(OrderStatusEnum.NOT_SHIPPED.getCode()));
        // 待收货
        result.setReceivedCount(map.get(OrderStatusEnum.SHIPPED.getCode()));
        // 已完成
        result.setCompleteCount(map.get(OrderStatusEnum.COMPLETE.getCode()));
        // 已取消
        result.setCanceledCount(map.get(OrderStatusEnum.CANCEL.getCode()));
        // 售后
        Integer m = map.get(OrderStatusEnum.APPLY_REFUND.getCode()) == null ? 0 : map.get(OrderStatusEnum.APPLY_REFUND.getCode());
        Integer n = map.get(OrderStatusEnum.REJECTED_SUCCESS.getCode()) == null ? 0 : map.get(OrderStatusEnum.REJECTED_SUCCESS.getCode());
        result.setRefundCount(m + n);
        return result;
    }

    @Override
    public OrderDataResponse pickingOrderData() {
        OrderDataResponse result = new OrderDataResponse();
        User currentUser = userService.getInfo();
        //1=待付款2=待确认3=待发货4=待收货5=已完成6=售后（退款中，已退款）9=全部（包括1.2.3.4.5.6以及已取消)
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setUid(currentUser.getUid());
        List<StoreOrderInfo> list = storeOrderInfoService.getOrderCount(storeOrderPram);
        Map<Integer, Integer> map = list.stream().collect(Collectors.toMap(StoreOrderInfo::getStatus, StoreOrderInfo::getId));
        // 待付款
        result.setUnPaidCount(map.get(OrderStatusEnum.UNPAID.getCode()));
        //待确认
        result.setConfirmedCount(map.get(OrderStatusEnum.CONFIRM.getCode()));
        // 待发货
        result.setUnShippedCount(map.get(OrderStatusEnum.NOT_SHIPPED.getCode()));
        // 待收货
        result.setReceivedCount(map.get(OrderStatusEnum.SHIPPED.getCode()));
        // 已完成
        result.setCompleteCount(map.get(OrderStatusEnum.COMPLETE.getCode()));
        // 售后
        Integer m = map.get(OrderStatusEnum.APPLY_REFUND.getCode()) == null ? 0 : map.get(OrderStatusEnum.APPLY_REFUND.getCode());
        Integer n = map.get(OrderStatusEnum.REJECTED_SUCCESS.getCode()) == null ? 0 : map.get(OrderStatusEnum.REJECTED_SUCCESS.getCode());
        result.setRefundCount(m + n);
        return result;
    }

    /**
     * 查询退款理由
     *
     * @return 退款理由集合
     */
    @Override
    public List<String> getRefundReason() {
        String reasonString = systemConfigService.getValueByKey("stor_reason");
        reasonString = CrmebUtil.UnicodeToCN(reasonString);
        reasonString = reasonString.replace("rn", "n");
        return Arrays.asList(reasonString.split("\\n"));
    }

    /**
     * 计算订单价格
     *
     * @param request  订单提交参数
     * @param orderKey 订单key
     * @return 订单计算结果
     */
    @Override
    public HashMap<String, Object> computedOrder(OrderComputedRequest request, String orderKey) {
        HashMap<String, Object> resultMap = new HashMap<>();
        User currentUser = userService.getInfo();
        // 检查订单是否存在
        if (orderUtils.checkOrderExist(orderKey, currentUser.getUid())) {
            OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderKey, orderKey);
            OrderPayResponse orderPayResponse = new OrderPayResponse("extend_order", itemResponse);
            resultMap.put("result", orderPayResponse);
            return resultMap;
        }
        // todo 拼团砍价秒杀 二期

        String existCacheOrder = orderUtils.cacheGetOrderInfo(userService.getUserIdException(), orderKey);
        if (null == existCacheOrder)
            throw new CrmebException("订单已过期,请刷新当前页面!");
        ConfirmOrderResponse cor = JSONObject.parseObject(existCacheOrder, ConfirmOrderResponse.class);
        OrderCreateRequest orderCreateRequest = new OrderCreateRequest();
        BeanUtils.copyProperties(request, orderCreateRequest);
        ComputeOrderResponse priceGroup = orderUtils.computedOrder(orderCreateRequest, cor, orderKey);
        if (null == priceGroup) {
            throw new CrmebException("计算失败");
        } else {
            Integer leaderId = request.getLeaderId();
            if(null != leaderId && 0 != leaderId){
                BigDecimal packagePrice = priceGroup.getPackagePrice();
                if(packagePrice != null && packagePrice.compareTo(BigDecimal.ZERO) > 0){
                    priceGroup.setPayPrice(packagePrice);
                }
            }
            OrderPayItemResponse resultItemResponse = new OrderPayItemResponse(orderKey, priceGroup);
            OrderPayResponse resultOrderPayResponse = new OrderPayResponse("NONE", resultItemResponse);
            resultMap.put("result", resultOrderPayResponse);
            return resultMap;
        }
    }

    @Override
    public HashMap<String, Object> computedPickingOrder(OrderComputedRequest request, String orderKey) {
        HashMap<String, Object> resultMap = new HashMap<>();
        User currentUser = userService.getInfo();
        // 检查订单是否存在
        if (orderUtils.checkOrderExist(orderKey, currentUser.getUid())) {
            OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderKey, orderKey);
            OrderPayResponse orderPayResponse = new OrderPayResponse("extend_order", itemResponse);
            resultMap.put("result", orderPayResponse);
            return resultMap;
        }
        // todo 拼团砍价秒杀 二期

        String existCacheOrder = orderUtils.cacheGetOrderInfo(userService.getUserIdException(), orderKey);
        if (null == existCacheOrder)
            throw new CrmebException("订单已过期,请刷新当前页面!");
        ConfirmOrderResponse cor = JSONObject.parseObject(existCacheOrder, ConfirmOrderResponse.class);
        OrderCreateRequest orderCreateRequest = new OrderCreateRequest();
        BeanUtils.copyProperties(request, orderCreateRequest);
        ComputeOrderResponse priceGroup = orderUtils.computedPickingOrder(orderCreateRequest, cor, orderKey);
        if (null == priceGroup) {
            throw new CrmebException("计算失败");
        } else {
            OrderPayItemResponse resultItemResponse = new OrderPayItemResponse(orderKey, priceGroup);
            OrderPayResponse resultOrderPayResponse = new OrderPayResponse("NONE", resultItemResponse);
            resultMap.put("result", resultOrderPayResponse);
            return resultMap;
        }
    }

    /**
     * 订单物流查看
     *
     * @param orderId 订单id
     */
    @Override
    public Object expressOrder(String orderId) {
        HashMap<String, Object> resultMap = new HashMap<>();
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setOrderId(orderId);
        StoreOrder existOrder = storeOrderService.getByEntityOne(storeOrderPram);
        if (null == existOrder)
            throw new CrmebException("未找到该订单信息");
        if (!existOrder.getDeliveryType().equals(Constants.ORDER_LOG_EXPRESS) || StringUtils.isBlank(existOrder.getDeliveryType()))
            throw new CrmebException("该订单不存在快递订单号");

        PageParamRequest page = new PageParamRequest();
        page.setPage(1);
        page.setLimit(999);
        StoreOrderInfoSearchRequest storeOrderInfoPram = new StoreOrderInfoSearchRequest();
        storeOrderInfoPram.setOrderId(existOrder.getId());
        List<StoreOrderInfo> list = storeOrderInfoService.getList(storeOrderInfoPram, page);
        List<HashMap<String, Object>> cartInfos = new ArrayList<>();
        for (StoreOrderInfo storeInfo : list) {
            HashMap<String, Object> cartInfo = new HashMap<>();
            StoreCartResponse scr = JSONObject.parseObject(storeInfo.getInfo(), StoreCartResponse.class);
            cartInfo.put("cartNum", scr.getCartNum());
            cartInfo.put("truePrice", scr.getTruePrice());
            cartInfo.put("productInfo", scr.getProductInfo());
            cartInfos.add(cartInfo);
        }
        HashMap<String, Object> orderInfo = new HashMap<>();
        orderInfo.put("deliveryId", existOrder.getDeliveryId());
        orderInfo.put("deliveryName", existOrder.getDeliveryName());
        orderInfo.put("deliveryType", existOrder.getDeliveryType());
        orderInfo.put("cartInfo", cartInfos);

        resultMap.put("order", orderInfo);
        try {

            LogisticsResultVo expressInfo = logisticsService.info(existOrder.getDeliveryId(), null);
            resultMap.put("express", expressInfo);
        } catch (Exception ex) {
            log.warn("没有物流信息！orderId:{}", orderId);
        }
        return resultMap;
        //        expressService.getExpressInfo();

    }

    /**
     * 获取待评价信息
     *
     * @return
     */
    @Override
    public Object getReplyProduct(GetProductReply productReply) {
        HashMap<String, Object> resultMap = new HashMap<>();
        //        StoreOrder storeOrderPram = new StoreOrder();
        //        storeOrderPram.setUnique(unique);
        //        StoreOrder existOrder = storeOrderService.getByEntityOne(storeOrderPram);
        //        if(null== existOrder) throw new CrmebException("未找到该订单信息");
        StoreOrderInfoSearchRequest soinfoRequest = new StoreOrderInfoSearchRequest();
        soinfoRequest.setUnique(productReply.getUni());
        soinfoRequest.setOrderId(productReply.getOrderId());
        PageParamRequest pageRequest = new PageParamRequest();
        pageRequest.setLimit(999);
        pageRequest.setPage(1);
        List<StoreOrderInfo> orderInfos = storeOrderInfoService.getList(soinfoRequest, pageRequest);
        // 这里其实只能拿到一条信息
        for (StoreOrderInfo storeInfo : orderInfos) {
            HashMap<String, Object> cartInfo = new HashMap<>();
            StoreCartResponse scr = JSONObject.parseObject(storeInfo.getInfo(), StoreCartResponse.class);
            resultMap.put("cartNum", scr.getCartNum());
            cartInfo.put("truePrice", scr.getTruePrice());
            resultMap.put("productInfo", scr.getProductInfo());
            //            resultMap.put("orderInfo", existOrder);
            resultMap.put("productId", scr.getProductInfo().getId());
        }
        return resultMap;
    }

    /**
     * 更换支付类型
     *
     * @param payType 支付类型
     */
    @Override
    public boolean changePayType(String payType, String orderId) {
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setOrderId(orderId);
        StoreOrder existOrder = storeOrderService.getByEntityOne(storeOrderPram);
        if (null == existOrder)
            throw new CrmebException("未找到订单信息");
        existOrder.setPayType(payType);
        return storeOrderService.updateById(existOrder);
    }

    /**
     * 方法已失效
     * auth: daigb
     */
    @Override
    public OrangeWechatAppletConfigVo getOrangeConfig() {
        OrangeWechatAppletConfigVo vo = new OrangeWechatAppletConfigVo();
        vo.setEvn(evn);
        vo.setOriginalld(originalld);
        vo.setPayCatalog(payCatalog);
        vo.setWxAppId(wxAppId);
//        if (!orderType) {
//            vo.setOrange(true);
//        } else {
        vo.setOrange(false);
//        }
        return vo;
    }

    /**
     * 积分抵扣是否开启
     */
    @Override
    public Object enableIntegral() {
        //当前用户是否开启积分抵扣
        User info = userService.getInfo();
        /*Integer enableIntegral = channelMerchantService.getById(info.getMerId()).getEnableIntegral();
        EnableIntegralResponse enableIntegralResponse = new EnableIntegralResponse();
        enableIntegralResponse.setEnableIntegral(enableIntegral);
        if (enableIntegral==1) {
            enableIntegralResponse.setIntegralRate(systemConfigService.getValueByKey(Constants.CONFIG_KEY_INTEGRAL_RATE));
            enableIntegralResponse.setIntegralRateOrderGive(systemConfigService.getValueByKey(Constants.CONFIG_KEY_INTEGRAL_RATE_ORDER_GIVE));
        }*/

        MemberPointsManagement management = memberPointsManagementService.getOne(Wrappers.lambdaQuery(MemberPointsManagement.class).eq(MemberPointsManagement::getMerId, info.getMerId()));

        return management;
    }

    /**
     * 积分抵扣是否开启
     *
     * @param merId 当前登录的商户
     */
    @Override
    public Object enableIntegral(Integer merId) {
        //当前用户是否开启积分抵扣
        MemberPointsManagement management = Optional.ofNullable(memberPointsManagementService.getOne(Wrappers.<MemberPointsManagement>lambdaQuery().eq(MemberPointsManagement::getMerId, merId).last("LIMIT 1"))).orElse(new MemberPointsManagement());
        EnableIntegralResponse enableIntegralResponse = new EnableIntegralResponse();
        enableIntegralResponse.setEnableIntegral(BooleanUtils.isTrue(management.getPointsEnableFlag()) ? 1 : 0);
        if (enableIntegralResponse.getEnableIntegral() == 1) {
            enableIntegralResponse.setIntegralRate(management.getPointsRatio() + "");
            enableIntegralResponse.setIntegralRateOrderGive(management.getOrderOintsProportion() + "");
        }

        return enableIntegralResponse;
    }

    /**
     * 修改订单地址
     *
     * @param request
     * @return
     */
    @Override
    public boolean updateOrderAddress(UpdateOrderAddressRequest request) {
        int flag = storeOrderStatusService.count(Wrappers.lambdaQuery(StoreOrderStatus.class).eq(StoreOrderStatus::getOid, request.getOrderId()).eq(StoreOrderStatus::getChangeType, Constants.ORDER_USER_UPDATE_ADDRESS));
        if (flag > 0) {
            throw new CrmebException("用户只能修改一次地址");
        }
        //查询当前订单状态
        StoreOrder storeOrder = storeOrderService.getById(request.getOrderId());
        if (storeOrder == null || storeOrder.getIsDel()) {
            throw new CrmebException("订单不存在");
        }
        if (!OrderStatusEnum.UNPAID.getCode().equals(storeOrder.getStatus()) && !OrderStatusEnum.VERIFY.getCode().equals(storeOrder.getStatus())) {
            throw new CrmebException("用户只能修改待审核,待付款订单");
        }
        if (storeOrder.getShippingType() != 1) {
            throw new CrmebException("用户不能修改自提订单地址");
        }
        UserAddress userAddress = userAddressService.getById(request.getUserAddressId());
        if (userAddress == null || userAddress.getIsDel()) {
            throw new CrmebException("用户地址不存在");
        }
        if (storeOrder.getPickingId() > 0 && !userAddress.getAreaType().equals(storeOrder.getAreaType())) {
            throw new CrmebException("区域类型不正确");
        }
        if (!Objects.equals(userAddress.getAreaType(), storeOrder.getAreaType())) {
            throw new CrmebException("只能选择当前区域地址");
        }
        storeOrder.setIdCard(userAddress.getIdCard());
        storeOrder.setRealName(userAddress.getRealName());
        storeOrder.setUserPhone(userAddress.getPhone());
        storeOrder.setAreaType(userAddress.getAreaType());
        storeOrder.setUserAddress(userAddress.getProvince()
                + userAddress.getCity()
                + userAddress.getDistrict()
                + userAddress.getDetail());
        storeOrder.setProvince(userAddress.getProvince());
        storeOrder.setCity(userAddress.getCity());
        storeOrder.setDistrict(userAddress.getDistrict());
        storeOrder.setDetail(userAddress.getDetail());
        boolean b = storeOrderService.updateById(storeOrder);
        if (b) {
            storeOrderStatusService.createLog(request.getOrderId(), storeOrder.getOrderId(), Constants.ORDER_USER_UPDATE_ADDRESS, "用户修改地址");
        }
        return b;
    }

    @Override
    public boolean updateOrderToPhone(Integer id, String toPhone) {
        //查询当前订单状态
        StoreOrder storeOrder = storeOrderService.getById(id);
        if (storeOrder == null || storeOrder.getIsDel()) {
            throw new CrmebException("订单不存在");
        }
        if (storeOrder.getShippingType() == 1) {
            throw new CrmebException("该订单不是自提订单");
        }
        if (!OrderStatusEnum.UNPAID.getCode().equals(storeOrder.getStatus()) && !OrderStatusEnum.VERIFY.getCode().equals(storeOrder.getStatus())) {
            throw new CrmebException("用户只能修改待审核,待付款订单");
        }
        storeOrder.setToPhone(toPhone);
        boolean b = storeOrderService.updateById(storeOrder);
        if (b) {
            storeOrderStatusService.createLog(id, storeOrder.getOrderId(), "update_toPhone", "用户修改自提手机号");
        }
        return b;
    }

    /**
     * 订单可用优惠券列表
     *
     * @param cartIds
     * @param isNew
     * @param merId
     * @return
     */
    @Override
    public List<StoreCouponUserResponse> listConfirmCoupons(List<Integer> cartIds, boolean isNew, Integer merId) {
        // 同确认订单
        List<StoreCartResponse> storeCartResponse = new ArrayList<>();
        User currentUserInfo = userService.getInfo();
        ChannelMerchant channelMerchant = channelMerchantService.getById(merId);
        if (isNew) {
            storeCartResponse = orderUtils.getCacheOrderAgain(cartIds.get(0) + "");

        } else {
            storeCartResponse = storeCartService.getListByUserIdAndCartIds(currentUserInfo.getUid(), cartIds, channelMerchant, null);
        }
        // 获取有效优惠券
        UserAddress defaultAddress = userAddressService.getDefault();
        //        if(null == defaultAddress) throw new CrmebException("未配置默认收货地址");

        // 计算订单金额
        PriceGroupResponse orderPriceGroup = priceUtil.getOrderPriceGroup(storeCartResponse, defaultAddress, merId);
        //2c运税费加到价格里
        if (channelMerchant != null && channelMerchant.getAppletType() == 1 && orderPriceGroup.getTaxAndSecondPrice() != null) {
            orderPriceGroup.setPayPrice(orderPriceGroup.getPayPrice().add(orderPriceGroup.getTaxAndSecondPrice()));
            orderPriceGroup.setTaxAndSecondPrice(new BigDecimal(0));
        }

        return orderUtils.getCanUseCouponList(storeCartResponse, true, orderPriceGroup, defaultAddress, channelMerchant);
    }

    @Override
    public Object submitPickingOrder(OrderCreateRequest orderRequest, String key, String ip) {
        User currentUser = userService.getInfo();
        // 检查订单是否存在
        if (orderUtils.checkOrderExist(key, currentUser.getUid())) {
            throw new CrmebException(key + "订单已存在");
        }
        String existCacheOrder = orderUtils.cacheGetOrderInfo(userService.getUserIdException(), key);
        if (null == existCacheOrder) {
            throw new CrmebException("订单已过期,请刷新当前页面!");
        }
        ConfirmOrderResponse cor = JSONObject.parseObject(existCacheOrder, ConfirmOrderResponse.class);
        // 检查订单状态
        return orderUtils.createOrder(orderRequest, cor, orderRequest.getIsChannel(), orderRequest.getStoreId(), key);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePickingProduct(UpdatePickingProductRequest request) {
        StoreOrder storeOrder = storeOrderService.getById(request.getOrderId());
        if (storeOrder == null) {
            throw new CrmebException("该订单不存在");
        }
        StoreOrderInfoPicking orderInfoPicking = storeOrderInfoPickingService.getById(request.getOrderInfoId());
        if (orderInfoPicking == null || orderInfoPicking.getIsDel() == 1) {
            throw new CrmebException("该商品不存在");
        }
        if (request.getNum() == 0) {
            storeOrderInfoPickingService.update(Wrappers.<StoreOrderInfoPicking>lambdaUpdate()
                    .set(StoreOrderInfoPicking::getIsDel, 1).eq(StoreOrderInfoPicking::getId, request.getOrderInfoId()));
        } else if (request.getNum() > 0) {
            //库存校验
            //StoreProductAttrValue attrValue = storeProductAttrValueService.getById(orderInfoPicking.getUnique());
            StoreProductAttrValue attrValue = storeProductAttrValueService.getOne(Wrappers.lambdaQuery(StoreProductAttrValue.class)
                    .eq(StoreProductAttrValue::getSourceSkuId, orderInfoPicking.getUnique())
                    .eq(StoreProductAttrValue::getProductId, orderInfoPicking.getProductId())
                    .last("LIMIT 1"));
            if (attrValue == null || attrValue.getStock() < request.getNum()) {
                throw new CrmebException("库存不足");
            }
            storeOrderInfoPickingService.update(Wrappers.<StoreOrderInfoPicking>lambdaUpdate()
                    .set(StoreOrderInfoPicking::getNum, request.getNum()).eq(StoreOrderInfoPicking::getId, request.getOrderInfoId()));
        } else {
            throw new CrmebException("数量异常");
        }
        //处理主订单金额
        List<StoreOrderInfoPicking> infoPickingList = storeOrderInfoPickingService.list(Wrappers.<StoreOrderInfoPicking>lambdaQuery()
                .eq(StoreOrderInfoPicking::getOrderId, request.getOrderId()).eq(StoreOrderInfoPicking::getIsDel, 0));
        BigDecimal payPrice = BigDecimal.ZERO;
        BigDecimal payPostage = BigDecimal.ZERO;
        Integer num = 0;
        for (StoreOrderInfoPicking info : infoPickingList) {
            payPrice = payPrice.add(info.getPayPrice().multiply(BigDecimal.valueOf(info.getNum())));
            payPostage = payPostage.add(info.getSecondPrice().multiply(BigDecimal.valueOf(info.getNum())));
            num += info.getNum();
        }
        storeOrder.setPayPrice(payPrice);
        storeOrder.setPayPostage(payPostage);
        storeOrder.setTotalPrice(payPrice.subtract(payPostage));
        storeOrder.setTotalNum(num);
        storeOrderService.updateById(storeOrder);
        return true;
    }

    @Override
    public boolean tracking(StoreOrderSendRequest request) {
        try {
            StoreOrder storeOrder = storeOrderService.getById(request.getId());
            if (null == storeOrder) {
                throw new CrmebException("没有找到订单信息");
            }
            StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getOrderInfoId());
            if (null == storeOrderInfo) {
                throw new CrmebException("没有找到订单信息!");
            }
            StoreOrderRefundApply refundApply = storeOrderRefundApplyService.getOne(Wrappers.<StoreOrderRefundApply>lambdaQuery().eq(StoreOrderRefundApply::getInfoId, request.getOrderInfoId()).orderByDesc(StoreOrderRefundApply::getId).last("LIMIT 1"));
            if (refundApply == null) {
                throw new CrmebException("没有找到该订单退货信息");
            }
            if (refundApply.getDeliveryId() != null) {
                throw new CrmebException("该退货已发货");
            }
            if (refundApply.getProcessType() == 2) {
                throw new CrmebException("该订单拒绝退款");
            }
            //快递信息
            Express express = expressService.info(Integer.parseInt(request.getExpressId()));
            //新增物流信息
            OrderInfoDeliveryRequest delivery = new OrderInfoDeliveryRequest();
            delivery.setOrderInfoId(request.getOrderInfoId());
            delivery.setDeliveryCompany(express.getName());
            delivery.setDeliveryNumber(request.getExpressCode());
            delivery.setName(request.getName());
            delivery.setDeliveryCode(express.getCode());
            delivery.setPhone(request.getPhone());
            delivery.setExpressId(Integer.parseInt(request.getExpressId()));
            delivery.setChannel(request.getChannel());
            if (!Objects.isNull(request.getLevel())) {
                delivery.setLevel(request.getLevel());
            }
            delivery.setChannel(request.getChannel());
//            orderInfoDeliveryService.addDelivery(delivery);
            OrderInfoDelivery orderInfoDelivery = new OrderInfoDelivery();
            BeanUtils.copyProperties(delivery, orderInfoDelivery);
            orderInfoDeliveryService.save(orderInfoDelivery);
            refundApply.setDeliveryId(orderInfoDelivery.getId());
            storeOrderRefundApplyService.updateById(refundApply);
            storeOrderStatusService.createLog(request.getId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_LOG_EXPRESS, "用户已发货");
            return true;
        } catch (Exception e) {
            throw new CrmebException("快递发货失败！" + e.getMessage());
        }

    }

    ///////////////////////////////////////////////////////////////////// 自定义方法

    /**
     * 仅仅支付
     * 订单支付完之后给出状态值 以便前端使用， 后期这里也可以抽出对象
     * ORDEREEXIST, EXTENDORDER, PAYERROR, SUCCESS, WECHATPAY, PAYDEFICIENCY, WECHATH5PAY
     *
     * @param request
     * @param ip
     * @param resultMap
     * @param existStoreOrder
     * @return
     */
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean doPayOrder(OrderPayRequest request, String ip, HashMap<String, Object> resultMap, StoreOrder existStoreOrder) {
        existStoreOrder.setPayType(request.getPaytype());
        //        if(request.getFrom().equals(Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM)){
        //            existStoreOrder.setPayType(Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM);
        //        }
        CreateOrderResponseVo orderPayResult = orderPayService.payOrder(existStoreOrder.getId(), request.getFrom(), ip);
        // 下面组装前端所需数据
        switch (existStoreOrder.getPayType()) {
            case Constants.PAY_TYPE_WE_CHAT:
            case Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM:
                if (existStoreOrder.getPayType().equals(Constants.PAY_TYPE_WE_CHAT_FROM_H5)) {
                    OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderPayResult.getPrepayId(), existStoreOrder.getOrderId());
                    OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_H5_PAY", itemResponse);
                    resultMap.put("result", orderPayResponse.getResult());
                    resultMap.put("status", "WECHAT_H5_PAY");
                    resultMap.put("jsConfig", orderPayResult.getTransJsConfig());
                    return true;
                } else {
                    OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderPayResult.getPrepayId(), existStoreOrder.getOrderId());
                    OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_PAY", itemResponse);
                    resultMap.put("result", orderPayResponse.getResult());
                    resultMap.put("status", "WECHAT_PAY");
                    resultMap.put("jsConfig", orderPayResult.getTransJsConfig());
                    return true;
                }
                //            case Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM:
                //                OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderPayResult.getPrepayId(), existStoreOrder.getOrderId());
                //                OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_PAY",itemResponse);
                //                resultMap.put("result", orderPayResponse.getResult());
                //                resultMap.put("status","WECHAT_PAY");
                //                resultMap.put("jsConfig", orderPayResult.getTransJsConfig());
                //                return true;
            case Constants.PAY_TYPE_YUE:
                //                if(orderPayResult.getReturnCode().equals("1")){
                //                OrderPayItemResponse itemResponse = new OrderPayItemResponse(request.getUni(), existStoreOrder.getOrderId());
                OrderPayResponse orderPayResponseY = new OrderPayResponse("SUCCESS", new OrderPayItemResponse(request.getUni(), existStoreOrder.getOrderId()));
                resultMap.put("result", orderPayResponseY.getResult());
                resultMap.put("status", "SUCCESS");
                //                }
                return true;
            case Constants.PAY_TYPE_OFFLINE:
                StoreOrder storeOrderOffLinePram = new StoreOrder();
                storeOrderOffLinePram.setOrderId(existStoreOrder.getOrderId());
                storeOrderOffLinePram.setPayType(Constants.PAY_TYPE_OFFLINE);
                boolean offlineResult = storeOrderService.updateByEntity(storeOrderOffLinePram);
                if (offlineResult) {
                    resultMap.put("result", "订单创建成功");
                    return true;
                } else {
                    throw new CrmebException("支付失败");
                }
        }
        return false;
    }

	@Override
	@Async("taskExecutor")
	public void pushOrderByJky(StoreOrder storeOrder) {
		if(!jkyPush) {
			return;
		}
		List<ChannelMerchant> merchantList = channelMerchantService.list(Wrappers.<ChannelMerchant>lambdaQuery()
        		.eq(ChannelMerchant::getChannelType, 3)
        		.apply(CrmebUtil.getFindInSetSql("confirm_ids", storeOrder.getMerId()))
        		);
        for (ChannelMerchant merchant : merchantList) {
            List<Integer> supplierIdList = JSONArray.parseArray(merchant.getSuppliersIds(), Integer.class);
            Supplier supplier = supplierService.getById(supplierIdList.get(0));
            log.info("--------------- 自营商户订单推送至{}, 商户号: {}, 订单号: {} ---------------", merchant.getChannelName(), storeOrder.getMerId(), storeOrder.getId());
            List<StoreOrderInfo> orderInfoList = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, storeOrder.getId()));
            if (orderInfoList.size() < 1) {
                return;
            }
            List<StoreOrderInfoVo> storeOrderInfoVoList = new ArrayList<>();
            for (StoreOrderInfo storeOrderInfo : orderInfoList) {
                StoreProduct product = Optional.ofNullable(storeProductService.getOne(Wrappers.lambdaQuery(StoreProduct.class)
                		.eq(StoreProduct::getId, storeOrderInfo.getProductId()))
                		).orElse(new StoreProduct());
                //解析商品详情JSON
                StoreOrderInfoVo StoreOrderInfoVo = new StoreOrderInfoVo();
                BeanUtils.copyProperties(storeOrderInfo, StoreOrderInfoVo, "info");
                StoreOrderInfoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
                StoreOrderInfoVo.getInfo().setIsReply(
                        storeProductReplyService.isReply(StoreOrderInfoVo.getUnique(), "product", StoreOrderInfoVo.getOrderId()).size()
                );
                StoreOrderInfoVo.getInfo().getProductInfo().setSupplierName(product.getSuppliersName());
                storeOrderInfoVoList.add(StoreOrderInfoVo);
            }
            AbstractStoreOrderService storeOrderService = storeOrderFactory.getStoreOrderService(BarCodeEnum.valueStringOf(supplier.getBarcode()));
            storeOrderService.addChannelOrder(storeOrder, storeOrderInfoVoList);
        }		
	}

}
